2

I am trying to achieve something that should be simple but seems impossible in PHP ActiveRecord.

In the simplified example I created, I have two models, Person and Exchange, and two tables, people(id, name) and exchange(id, user_from_id, user_to_id, comment). exchange.user_from_id and exchange.user_to_id have a foreign key constraint referencing people.id.

So when I run the following code:

$exchange = Exchange::first();
echo $exchange->user_from_id;
echo $exchange->user_from_id->name;

I would expect the first echo to fail and the second one to succeed. Instead, the first one succeeds and prints the litteral value of exchange.user_from_id and then obviously the second one generates a "Trying to get property of non-object" warning.

The result is the same with or without adding the following to Exchange:

static $belongs_to = array(
    array('user_from_id', 'class_name' => 'Person'),
    array('user_to_id', 'class_name' => 'Person')
);

What should I change in my code to make it so that $exchange->user_from_id returns an instance of the Person class?

1 Answer 1

2

It turns out I had misunderstood how BelongsTo work. I thought it somehow bound a property of a Model, corresponding to an attribute, to a different Model, but I realise now it creates a new property, which you then have to explicitely associate with an attribute using the foreign_key option.

Concretely, this is what I had to add to the Exchange:

static $belongs_to = array(
    array('user_from',
          'class_name' => 'Person',
          'foreign_key' => 'user_from_id'),
    array('user_to',
          'class_name' => 'Person',
          'foreign_key' => 'user_to_id')
);

Then, using this code:

$exchange = Exchange::first();
echo $exchange->user_from;
echo $exchange->user_from->name;

I finally got what I expected: a fatal error on the first echo and the second one printing people.name where people.id = exchange.user_from_id.

This also made it possible to use eager loading of the two people objects with:

$exchange = Exchange::first(array('include' => array('user_from', 'user_to')));
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.