jgautier's avatar

One to One Relationship - how to get direct accessors to all related attributes ?

Hi,

I have two models related by a one to one relationship : let's say model1 and model2. Let's say model2 have 2 attributes : attr1 and attr2

I'd like to be able to get model2's attributes directly from model1, like that : $model1->attr1 $model1->attr2

I know I could define custom accessors inside model1 class, by define public functions getAttr1Attribute() and getAttr2Attribute().

But, two questions :

  • is it the better way to do that ?
  • is there a way to define these accessors "dynamically" ? I mean : something like looping on all model2's attributes and define an accessor for each ?

Sorry if my question is trivial and/or my english is poor... Thanks for your answers.

JG

0 likes
2 replies
LaryAI's avatar
Level 58

One way to achieve this is by defining a one-to-one relationship between the two models and then using the magic __get() method to dynamically access the related model's attributes.

Here's an example:

// Model1.php

class Model1 extends Model
{
    public function model2()
    {
        return $this->hasOne(Model2::class);
    }

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

        return parent::__get($key);
    }
}
// Model2.php

class Model2 extends Model
{
    // ...
}

With this setup, you can access the related model's attributes directly from Model1 like this:

$model1 = Model1::find(1);
$model1->model2; // returns the related Model2 instance
$model1->attr1; // returns the value of Model2's "attr1" attribute
$model1->attr2; // returns the value of Model2's "attr2" attribute

Note that this approach assumes that the related model's attributes have the same names as the accessors you want to define on Model1. If that's not the case, you'll need to modify the __get() method accordingly.

jgautier's avatar

@LaryAI Thanks IA ! But, in fact, I've had to write this code instead :

public function __get($key)
    {
        if ($this->model2() && $this-> model2()->first()->getAttribute($key)) {
            return $this-> model2()->first()->getAttribute($key);
        }
        return parent::__get($key);
    }

Please or to participate in this conversation.