skip to Main Content

I am on Laravel 10.

I am using casting of a json column in the following way:

protected $casts = [
        'meta' => 'collection',
        ...
];

When I am trying to update a collection value directly, e.g.

$model->meta->put('test', 100);
$model->save();

nothing happens.

When I assign variable as-is, it works fine

$model->meta = ['test' => 100];
$model->save();

but what if I need to update/add a single member only?

I have found the following workaround but is this the expected behaviour?

$meta = $model->meta;
$meta->put('test', 100);
$model->meta = $meta;
$model->save();

It seems that only direct assigning works in such case and that cast collection does not support any of its write functionality

3

Answers


  1. To cast an Eloquent column as a collection, you need to define a cast on your model. Here’s how you can do it:

    Let’s say you have a model named Post and you want to cast the meta_data column as a collection.

    Open your Post model located in app/Models/Post.php.

    Inside the Post model class, define the $casts property. This property is an associative array where the keys represent the column names you want to cast and the values represent the data types you want to cast to.

    To cast a column as a collection, you can use the collection data type.

        namespace AppModels;
    
    use IlluminateDatabaseEloquentModel;
    
    class Post extends Model
    {
        protected $casts = [
            'meta_data' => 'collection',
        ];
    }
    

    In this example, the meta_data column will be automatically cast to a Laravel collection when you retrieve it using Eloquent. You can access collection methods directly on the meta_data attribute.

    Remember to update the column name and the model class name according to your actual use case.

    Login or Signup to reply.
  2. try casting as collection AsCollection

    use IlluminateDatabaseEloquentCastsAsCollection;
    
    
    protected $casts = [
      'meta' => AsCollection::class,
      ...
    ];
    
    Login or Signup to reply.
  3. Solution (Laravel 8.28 or higher)

    Need use IlluminateDatabaseEloquentCastsAsCollection instead of 'collection'.

    In the $casts array, you can define the types of individual keys. By specifying the classes of the types (where necessary), Laravel automatically handles the conversion. This is why the specific use of AsCollection::class is required.

    namespace AppModels;
    
    use IlluminateDatabaseEloquentModel;
    use IlluminateDatabaseEloquentCastsAsCollection;
    
    class Item extends Model
    {
      protected $casts = [
        'meta' => AsCollection::class, // automatically convert value of 'meta' to Collection::class
      ];
    }
    
    More information


    Solution (Laravel 7.x or lower)

    AsCollection is available by default in Laravel 8.x or higher versions. If you need the collection feature in an older version, you will need to create a custom cast yourself.

    Or alternately can use 'array' cast:

    namespace AppModels;
    
    use IlluminateDatabaseEloquentModel;
    
    class Item extends Model
    {
      protected $casts = [
        'meta' => 'array', // automatically convert value of 'meta' to array
      ];
    }
    
    More information
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search