Search code examples
phplaravelcastinglaravel-5eloquent

Laravel 5 Eloquent, How to set cast attribute dynamically


In laravel 5.1 there is new feature called Attribute Casting, well documented at here : http://laravel.com/docs/5.1/eloquent-mutators#attribute-casting

My question is, it is possible to make attribute casting dynamically ?

for example, I have a table with columns :

id | name          | value       | type    |
1  | Test_Array    | [somearray] | array   |
2  | Test_Boolean  | someboolean | boolean |

it is possible to set value attribute cast, depends on type field, that work both in write(create/update) and fetch ?


Solution

  • You'll need to overwrite Eloquent model's getCastType() method in your model class:

    protected function getCastType($key) {
      if ($key == 'value' && !empty($this->type)) {
        return $this->type;
      } else {
        return parent::getCastType($key);
      }
    }
    

    You'll also need to add value to $this->casts so that Eloquent recognizes that field as castable. You can put the default cast there that will be used if you didn't set type.

    Update:

    The above works perfectly when reading data from the database. When writing data, you have to make sure that type is set before value. There are 2 options:

    1. Always pass an array of attributes where type key comes before value key - at the moment model's fill() method respects the order of keys when processing data, but it's not future-proof.

    2. Explicitely set type attribute before setting other attributes. It can be easily done with the following code:

      $model == (new Model(['type' => $data['type']))->fill($data)->save();