Home  >  Q&A  >  body text

How to update Laravel Eloquent column cast to collection

I am using Laravel 10.

I utilize the conversion of JSON columns in the following way:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
  protected $casts = [
    'meta' => 'collection', // here
  ];
}

For example, when trying to update a value in a collection directly:

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

No response.

When I assign the variable as is, it works fine.

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

But what if I only need to update/add a single element?

I found the following workaround, but is this expected behavior?

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

In this case, only direct assignment seems to work, and casting the collection doesn't seem to support any of its write capabilities.

P粉741678385P粉741678385177 days ago342

reply all(2)I'll reply

  • P粉019353247

    P粉0193532472024-03-31 00:48:23

    Try to convert it to a collection AsCollection

    use Illuminate\Database\Eloquent\Casts\AsCollection;
    
    
    protected $casts = [
      'meta' => AsCollection::class,
      ...
    ];
    

    reply
    0
  • P粉668113768

    P粉6681137682024-03-31 00:03:22

    Solution (Laravel 8.28 or higher)

    Need to use Illuminate\Database\ Eloquent\Casts\AsCollection instead of 'collection'.

    In the $casts array, you can define the type of each key. Laravel automatically handles the conversion by specifying the type's class (when necessary). That's why specifically using AsCollection::class< /a> is required.

    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\Casts\AsCollection;
    
    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 Available by default in Laravel 8.x or higher. If you need the set functionality from older versions, you'll need to create a custom cast yourself.

    Or you can also use 'array'Actor:

    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Item extends Model
    {
      protected $casts = [
        'meta' => 'array', // automatically convert value of 'meta' to array
      ];
    }
    
    More information

    reply
    0
  • Cancelreply