7

In laravel 5.4, I'm able to retrieve fillable fields by using fillable index of model instance.

$model = new AnyClass();
dd($model['fillable']);

The above code prints all fillable fields of AnyClass. But the same code prints null on laravel 5.6. I know I can retrieve fillable fields using $model->getFillable(). My question is what is the reason / why it is not working in laravel 5.6 but works in 5.4?

Vidhyut Pandya
  • 1,605
  • 1
  • 14
  • 27

5 Answers5

4

From the upgrade guide here I believe this is the answer to the question:

Model Methods & Attribute Names

To prevent accessing a model's private properties when using array access, it's no longer possible to have a model method with the same name as an attribute or property. Doing so will cause exceptions to be thrown when accessing the model's attributes via array access ($user['name']) or the data_get helper function.

Community
  • 1
  • 1
nakov
  • 13,938
  • 12
  • 60
  • 110
3

In Laravel 7, I'm doing this by calling the getFillable method on a new instance of my model. Like so:

$model = new MyModel();            
$fillable = $model->getFillable();
thePHPHero
  • 169
  • 3
  • 10
2

If you look at Laravel's source code you'll see the difference.

The Model class, which is extended by the application models, implements the ArrayAccess interface, which, among others, force the class to define the offsetGet method.

In Laravel 5.4 the offsetGet method looks like:

public function offsetGet($offset)
{
    return $this->$offset;
}

which means that if you call $model['fillable'], you actually call $model->offsetGet('fillable') which actually returns the fillable property of the class.

I couldn't find the Laravel 5.6 tag but I'm pretty sure it is the same code as Laravel 5.5.45. In this version the offsetGet method was changed to:

public function offsetGet($offset)
{
    return $this->getAttribute($offset);
}

which means that it actually returns the attribute if found or null otherwise.

Mihai Matei
  • 24,166
  • 5
  • 32
  • 50
1

Late to the party but I don't like the concept of having to always instance a Model, specially if you're using Eloquent serialization.

Let's say you wanted to build some filters, but wanted to whitelist the columns based on the model's fillable. You don't want to instance an entire model, so you can instead use reflection:

(new ReflectionClass(MyModel::class))->getDefaultProperties()['fillable']

See it working over at 3v4l.org - Here I demonstrate why you potentially wouldn't want to instance this model due to having serialization and always eager loading.

Jaquarh
  • 6,493
  • 7
  • 34
  • 86
-1

Change the property in the class to public $fillable = [ instead of protected $fillable = [

stokoe0990
  • 443
  • 3
  • 10