DEV Community

Discussion on: Laravel Greatest Trick Revealed: Magic Methods

Collapse
 
ystrauch profile image
Yaron Strauch • Edited

The magic method __set however has a trap that I fell into and needed many hours to debug.

Say you have your nice object, say Airplane, with a static function to initialise an airplane from some other data.

class Airplane extends \Illuminate\Database\Eloquent\Model {
   private $name;

   public static function fromSomething($foo) {
       $airplane = new Airplane();
       // do something awesome with $foo to derive the name
       $airplane->name = "Airbus";
       $airplane->save();
       return $airplane;
    }
}
Enter fullscreen mode Exit fullscreen mode

And obviously from somewhere else you call $airplane = Airplane.fromSomething($foo), and that part works as expected. But then you check your database (or fetch the model again through eloquent) and... It's empty! Well except for the created/modified timestamps. The rest is just empty.
The caveat: Php docs specify: __set() is run when writing data to inaccessible (protected or private) or non-existing properties. So it's not called because we have write access to the method! This means that all the cool eloquent magic to update your attributes is knocked out.
Solutions? Well just don't define the variables in your class. Which goes against all OOP tutorials out there (including this one) and any programming intuition. Or don't use static initialisers, which is a well-known design pattern. Or add it manually to attributes, therefore implementing framework functionality (variant: call __set yourself). Or use inheritance and use protected (but are they gonna be protected? Don't know either). Maybe there are more solutions? I will stick to the first one and stop defining the fields in my class.