Laravel 迁移数组类型(在数据库列中存储数组)

2022-08-30 10:36:47

我想在我的表中存储一个整数数组,但我在文档中找不到任何支持数组的类型,任何建议。

迁移:

public function up()
{
    Schema::create('pickups', function (Blueprint $table) {
        $table->increment('id');
        $table->boolean('default');
        $table->integer('shifts');  <<--------- HERE I want to store an array of integers
        $table->integer('status_id');

        $table->timestamps();
    });
}

答案 1

数据类型并非存在于所有数据库系统中,并且由于 Laravel 的 Schema Builder 与数据库无关,因此它不提供创建非通用数据类型列的方法。因此,您有两种选择:array

1.使用原始SQL语句来添加列,类似于下面的语句,我认为应该有效。虽然我不确定查询生成器或 Eloquent 是否可以正确处理这些类型的列:

DB::statement('ALTER TABLE pickups ADD COLUMN shifts integer[]');

2. 通过使用属性转换,使用 Eloquent 的可用解决方法。在迁移中,按如下方式创建列:json

public function up()
{
    Schema::create('pickups', function (Blueprint $table) {
        $table->increment('id');
        $table->boolean('default');
        $table->json('shifts');
        $table->integer('status_id');

        $table->timestamps();
    });
}

然后,您可以设置模型(如果尚未设置)并使用属性:Pickup$casts

class Pickup extends Model
{
    protected $casts = [
        'shifts' => 'array'
    ];
}

这将使 Eloquent 知道,当它从数据库获取数据时,它必须将列值转换为 .这只是模拟一个实际的数组,因为在数据库级别,列是类型,数组是序列化的。但是,在取消序列化列值时,Eloquent 会返回一个实际的整数数组,供您在代码中使用。下面是一个示例用例:shiftsarrayTEXT

// Create a new Pickup entry
$pickup = App\Pickup::create([
    'default' => true,
    'shifts' => '[1, 5, 7]', // you can easily assign an actual integer array here
    'status_id' => 1
]);

假设上面生成的条目与稍后检索条目时的条目相等:id1

$pickup = App\Pickup::find(1);
dump($pickup->shifts);

上面的代码将输出一个实际的整数数组:dump()

array:3 [▼
  0 => 1
  1 => 5
  2 => 7
]

答案 2

还有另一种更复杂的方法,但它允许使用架构生成器创建真正的本机数组。

PostgreSQL的示例。

  1. 注册新类型,该类型将通过扩展现有数据库架构语法解析为:int_arrayint[]
\DB::connection()->setSchemaGrammar(new class extends PostgresGrammar {
    protected function typeInt_array(\Illuminate\Support\Fluent $column)
    {
        return 'int[]';
    }
});

如果您只需要一次,则可以将此代码放在迁移中,也可以将其放入整个项目中。AppServiceProvider

  1. 现在,您可以在迁移中使用此类型:
Schema::table('users', function (Blueprint $table) {
    $table->addColumn('int_array', 'group_ids')->nullable();
});