Unnecessary lazy loading with relation in scope using afterFind #2108

Closed
davey-w opened this Issue Jan 22, 2014 · 6 comments

Projects

None yet

2 participants

@davey-w
davey-w commented Jan 22, 2014

For some reason, this problem (3ff408b) is back again since the last update (?). I'm making the join in a scope, placed in xxxxQuery extends ActiveQuery. When i'm using the relation in afterFind() an extra query for the relation is executed (and the join is made as well).

class UserQuery extends ActiveQuery
{

    /**
     * Only active and visible users, and get the main pic of each user
     */

    public function defaultScope()
    {
        $this->andWhere('accountStatus = 1 AND accountType <> 3');
        $this->joinWith('mainPhoto');
        return $this;
    }

}

Queries executed:

SELECT `user`.* FROM `user` LEFT JOIN `photo` ON (`user`.`id` = `photo`.`userId`) AND (photoType = 1) WHERE (accountStatus = 1 AND accountType <> 3) AND (`user`.`id`='62')

The next query is caused by this line in my afterFind method:

$this->thumb = isset($this->mainPhoto) ? $this->mainPhoto->file : Yii::$app->params['noPicUrl'];
SELECT * FROM `photo` WHERE (`userId`='62') AND (photoType = 1)
@cebe
Member
cebe commented Jan 22, 2014

Are you sure this query is fired in afterFind() and not because of joinWith() ?
Do you see the query once or twice in the log?

@davey-w
davey-w commented Jan 22, 2014

I double checked it, but you're right, the second query is fired because of joinWith(). When i disable my line in afterFind() and disabling $this->joinWith('mainPhoto') in UserQuery the second query isn't executing anymore. Enabling one of the two, or enabling both results in executing the second query again.

The query appears once in the log.

But still, when using joinWith(), the second query is still not necessary in a hasOne relation right?

@cebe
Member
cebe commented Jan 22, 2014

It is because we are not loading the relation data in the first query. This is by design of how AR works in yii2.

@cebe cebe closed this Jan 22, 2014
@davey-w
davey-w commented Jan 22, 2014

So in my case, $this->joinWith('mainPhoto'); is not necessary at all? Because the join is 'ignored' anyway?

@cebe
Member
cebe commented Jan 22, 2014

looks like it, yes. you can change it to $this->with('mainPhoto'); which will have the same effect. no need for it when fetching single user but will still be one query when fetching more than one.

@davey-w
davey-w commented Jan 23, 2014

Ok, that's clear, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment