Search code examples
laravelfunctionooprelationshipsbrackets

How does laravel model relationships work in core?


Consider this example

class SomeClass extends Model{
    public function user(){
        return $this->belongsTo('App\User');
    }
}
$instance = SomeClass::findOrFail(1);
$user = $instance->user;

how do laravel know(i mean in core) that $instance->user (without brackets) return related model?


Solution

  • Basically, whenever you try to access a property from a model, the __get magic method is invoked and it's something like the following:

    public function __get($key)
    {
        return $this->getAttribute($key);
    }
    

    As you can see that, the __get magic method calls another user defined method (getAttribute) which is something like the following:

    public function getAttribute($key)
    {
        if (! $key) {
            return;
        }
    
        // If the attribute exists in the attribute array or has a "get" mutator we will
        // get the attribute's value. Otherwise, we will proceed as if the developers
        // are asking for a relationship's value. This covers both types of values.
        if (array_key_exists($key, $this->attributes) ||
            $this->hasGetMutator($key)) {
            return $this->getAttributeValue($key);
        }
    
        // Here we will determine if the model base class itself contains this given key
        // since we do not want to treat any of those methods are relationships since
        // they are all intended as helper methods and none of these are relations.
        if (method_exists(self::class, $key)) {
            return;
        }
    
        return $this->getRelationValue($key);
    }
    

    In this case (for relation), the last line return $this->getRelationValue($key); is responsible for retrieving a relationship. Keep reading the source code, track each function calls and you'll get the idea. Start from Illuminate\Database\Eloquent\Model.php::__get method. Btw, this code is taken from latest version of Laravel but ultimately the process is same.

    Short summary: Laravel at first checks if the property/$kay being accessed is a property of a model or if it's an accessor method defined in the model itself then it simply returns that property otherwise it keeps further checking and if it founds a method defined in the model using that name (property/$kay) then it simply returns the relationship.