WeSee
WeSee

Reputation: 3772

Yii2 - hasOne alternative

In Yii2 we get related models using

class AnyClass {
    ...
    public function getUser()
    {
        return $this->hasOne(User::className(), ['id' => 'user_id']);
    }
}

What's the difference to this implementation?

class AnyClass {
    ...
    public function getUser()
    {
        return User::find()->where(['id' => $this->user_id]);
    }
}

I plan to use multiple compound keys and think the second version is much easier to extend with additional conditions for compound keys.

Upvotes: 2

Views: 1685

Answers (1)

csminb
csminb

Reputation: 2382

You can add compound keys or extra conditions in the relation itself:

public function getUser() {
    return $this->hasOne(User::className(), ['id' => 'user_id'])
       ->onCondition(['user.status' => 'active'])
}
public function getAdultUser() {
    return $this->getUser()->where(['user.adult' => 1])
}

Also keep in mind that the actual related records are loaded when you call it trough the getter method:

  • $anyClass->user will return an instance of User.
  • $anyClass->getUser() will return the ActiveQuery object.

So you can add extra conditions when and where you need them:

$anyClass->getUser()->where(['>', 'user.created_at', strtotime("previous month")])

Your implementation does not represent an actual relation between the two objects. It will work ONLY for lazy-loading data AND IF AnyClass is a loaded record: AnyClass::findOne(1)->user.

The only way to mange aggregate data or multiple results sets, where lazy-loading is impractical, is by using hasOne or hasMany, and specify the logical relation between your tables (in this case ['id' => 'user_id'] refers to the strict relation between AnyClass and User).

AnyClass::find()->with(`user`)->limit(1000); 
AnyClass::find()->joinWith(`user`);
SomeOtherClass::find()->joinWith('anyClass.user')->where('user.is_valid');

Upvotes: 9

Related Questions