Laravelでサポートされているcastのarrayを使えば配列型をarray取得できると思ってたが出来なかったので覚書
環境
Laravel 12.24.0
PostgreSQL 16.8
テーブル
CREATE TABLE hoge(
id SMALLSERIAL,
numlist DECIMAL(6,0)[],
create_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
update_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
delete_at TIMESTAMP,
PRIMARY KEY(id)
);
データ
INSERT INTO hoge (numlist, create_at,update_at)
VALUES
(array[1, 2], CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
,(array[3, 4], CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
中身はこのような感
select * from hoge;
id|numlist |create_at |update_at |delete_at|
--+---------+-----------------------+-----------------------+---------+
1|{1.0,2.0}|2026-09-16 19:11:49.011|2026-09-16 19:11:49.011| |
2|{3.0,4.0}|2026-09-16 19:11:49.011|2026-09-16 19:11:49.011| |
modelのcastへarrayを指定
protected function casts(): array
{
return [
'numlist' => array,
];
}
これで配列取得できるかと思ったのですが返ってきたのは文字列 {1,2} でした。
公式の Array and JSON Casting を確認して気がつきました。
arrayは配列型ではなくJSONデータ型を想定されたものでした。
MySQLには配列型はなくJSONデータ型がありますし
PostgreSQLもJSONデータ型あるのでJSONデータ型使ってれば問題なかった。
だけどテーブルは配列型のままでやってみる
カスタムcastを作ればできるだろうと作ってみました。
まずは make:cast コマンドで作る
php artisan make:cast PostgresIntegerArray
App\Casts 配下に PostgresIntegerArray.php が生成された。
カスタムcastには get と set を書く必要があるので以下のようにしてみた。
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;
class PostgresIntegerArray implements CastsAttributes
{
/**
* Cast the given value.
*
* @param array<string, mixed> $attributes
*/
public function get(Model $model, string $key, mixed $value, array $attributes): mixed
{
if (empty($value) || '{}' == $value) {
return [];
}
return array_map('intval', str_getcsv(trim($value, '{}')));
}
/**
* Prepare the given value for storage.
*
* @param array<string, mixed> $attributes
*/
public function set(Model $model, string $key, mixed $value, array $attributes): mixed
{
if (!is_array($value) || empty($value)) {
return '{}';
}
if (in_array(false, filter_var_array($value, FILTER_VALIDATE_INT), true)) {
throw new \Exception('column is type numeric[] but expression.');
}
return '{' . implode(',', $value) . '}' ;
}
}
※null考慮していませんのでこのままのコード利用時はご注意下さい。
modelへカスタムcastを適応
protected function casts(): array
{
return [
'numlist' => PostgresIntegerArray::class,
];
}
取得してみる
dd(Hoge::find(1)?->numlist);
無事に [1,2] が返って来ました。
まとめ
素直にカラムをJSONデータ型にすればわざわざカスタムCast作る必要が無かったのですが
配列型のままJOINしようと思っていたのでカラムを変更しませんでした。
使う前にはしっかり公式読みましょう。