6

I try to extend an extintig ˙PHP` Laravel model with some other fields, but I not found the right solution. I use PHP 7.1 with Laravel 6.2

Here is my code, what explain what I want to do.

The original model:

<?php
namespace App;

use App\Scopes\VersionControlScope;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $fillable = [
        'product_id',
        'name',
        'unit',
        // ...
    }

    // ... relations, custom complex functions are here
}

And as I imagined how to extend the original model:

<?php
namespace App;

class ProductBackup extends Product
{
    protected $fillable = array_merge(
        parent::$fillable,
        [
            'date_of_backup',
        ]
    );

    // ...
}

But now I get Constant expression contains invalid operations error message.

Can I extend shomehow my original model's $fillable array in the child class?

netdjw
  • 5,419
  • 21
  • 88
  • 162
  • I think you can assign `$fillable` from the constructor, there you can use methods (like array_merge) – CerebralFart May 28 '20 at 11:47
  • Or, alternatively to using `array_merge`, you can use something like `$this->fillable[] = 'field';` in your constructor. This is probably easier to read if there's only one or two added fields. – CerebralFart May 28 '20 at 11:48

1 Answers1

16

In your subclass constructor, you may use mergeFillable method from Illuminate\Database\Eloquent\Concerns\GuardsAttributes trait (automatically available for every Eloquent model).

/**
     * Create a new Eloquent model instance.
     *
     * @param  array  $attributes
     * @return void
     */
    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);

        $this->mergeFillable(['date_of_backup']);
    }
Shizzen83
  • 3,325
  • 3
  • 12
  • 32
  • Will this working with my custom variables too? For example if I have a `$myAttributes` array on parent, then can I use a `$this->mergeMyAttributes([...])` too? – netdjw May 28 '20 at 12:38
  • 1
    No you can't, unless implementing this method. – Shizzen83 May 28 '20 at 13:01
  • 3
    You want to call mergeFillable before the parent's constructor. The default constructor calls `$this->fill($attributes)`. Merging after that is too late, and fillable data will be lost. – Steven W Jun 28 '22 at 03:43
  • 1
    There is also a function `$this->mergeCasts([...])` for anyone interested, L10 [docs](https://laravel.com/api/10.x/Illuminate/Database/Eloquent/Concerns/HasAttributes.html#method_mergeCasts) – peter.babic Jun 11 '23 at 06:16