【问题标题】:Laravel migration array type (store array in database column)Laravel 迁移数组类型(将数组存储在数据库列中)
【发布时间】:2016-01-02 10:52:50
【问题描述】:

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

迁移:

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();
    });
}

【问题讨论】:

    标签: php arrays laravel types laravel-5.1


    【解决方案1】:

    array 数据类型并非存在于所有数据库系统中,并且因为 Laravel 的 Schema Builder 与数据库无关,它不提供创建非常见数据类型列的方法。所以你有两个选择:

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

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

    2. 通过 attribute casting 使用 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 知道,当它从数据库中获取数据时,它必须将 shifts 列值转换为 array。这只是模拟一个实际的数组,因为在数据库级别,列的类型是TEXT,并且数组是序列化的。但是,当反序列化列值时,Eloquent 会返回一个实际的整数数组供您在代码中使用。下面是一个示例用例:

    // 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
    ]);
    

    假设当您稍后检索条目时,上面生成了一个 id 等于 1 的条目:

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

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

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

    【讨论】:

    • 感谢@Bogdan 的出色回答,不幸的是,当我尝试使用'shifts' =&gt; [1, 5, 7], 创建新的取件条目时,我收到此错误消息PHP warning: preg_replace(): Parameter mismatch, pattern is a string while replacement is an array
    • 好的,现在就像关注'shifts' =&gt; '[1, 5, 7]',一样,谢谢:)
    • 我已经用全新安装的 Laravel 5.1 对此进行了测试,对我来说,它实际上可以在分配值时在数组周围不加引号。
    • 在这种情况下查询会起作用吗?如何?例如。我想要所有包含 shift 5 的记录。
    【解决方案2】:

    我通常将数组作为逗号分隔的字符串存储在列中,然后用explode检索它。

    所以在你的情况下,在存储时我会做这样的事情:

    $arraystring = implode(',',$array);
    
    $pickups->shifts = $arraystring; //$pickups is an instance of your Pickups model.
    
    //Then while retrieving I would just use;
    
    $array = $pickups->shifts ? explode(',',$pickups-shifts) : []; 
    /*just to make sure it is not an empty string 
    else you will get an error on explode.*/
    

    【讨论】:

      【解决方案3】:

      简单,用 json 存储你的数组整数:

      $table->json('shifts');
      

      【讨论】:

        【解决方案4】:

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

        PostgreSQL 示例。

        1. 注册新的 int_array 类型,通过扩展现有的 DB Schema Grammar 将解析为 int[]
        \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();
        });
        

        【讨论】:

        • 谢谢。我最喜欢这个 :) 上帝保佑!
        【解决方案5】:

        你可以简单地添加:

        protected $cast=['shifts'=>'array'];
        

        在您的模型类中,它适用于 laravel 8。

        【讨论】:

          猜你喜欢
          • 2016-08-25
          • 2021-06-19
          • 2016-10-06
          • 1970-01-01
          • 2017-01-24
          • 2018-01-28
          • 2022-10-17
          • 1970-01-01
          • 2016-09-17
          相关资源
          最近更新 更多