Yii2 eager loading not working

I have two entities in my database which are related by a one to many relationship: "User" and "Ad".

I have generated model classes using gii. This is what I have in my model class for User:




public function getAds()

{

    return $this->hasMany(Ad::className(), ['user' => 'id']);

}



and for my Ad model:




public function getUser0()

{

    return $this->hasOne(User::className(), ['id' => 'user']);

}



according to Yii2 documentation, In the controller when I do:




$ads = Ad::find()->all();

var_dump($ads[0]->user);



It should eagerly load user data from the DB but I only get the foreign key (1). Even when I try:




$ads = Ad::find()->with('user0')->all();

var_dump($ads[0]->user);



Its still the same.

If you have code:




$ads = Ad::find()->with('user0')->all();



You should check:




var_dump($ads[0]->user0);



If you want to check eager loading it will be more convenient to use find with asArray():





$ads = Ad::find()->asArray()->all();

var_dump($ads[0]); // array has no 'user0' key


$ads = Ad::find()->with('user0')->asArray()->all();

var_dump($ads[0]); // array has 'user0' key




With your db scheme - it’s absollutely normal that


$ads[0]->user

is an integer.

It will always be an integer regardless of using eager loading. But it can be confusing.

If you have access to change db scheme and your project isn’t so big - it will be better to rename some columns.

Use


..._id

for foreign key columns.

For example:




Ad

--------

id (primary key)

user_id (foreign key)



It’s more conveniently.

With this db scheme you can write:




public function getUser()

{

    return $this->hasOne(User::className(), ['id' => 'user_id']);

}



And then




$ads = Ad::find()->asArray()->all();

var_dump($ads[0]); // array has 'user_id' key (integer), but has no 'user' key


$ads = Ad::find()->with('user')->asArray()->all();

var_dump($ads[0]); // array has 'user_id' key (integer) AND 'user' key (with data from relative User entity)



Thanks a lot. I did the renaming and it’s a lot better now.

Another question:

Assume "ad" entity is related to "building" by a n:1 relation in the DB.Also "building" is related to "district" entity by a m:n relation.

so what I have in my ad model:


public function getBuilding()

    {

        return $this->hasOne(Building::className(), ['id' => 'building_id']);

    }

and in my building model:


public function getAds()

    {

        return $this->hasMany(Ad::className(), ['building_id' => 'id']);

    }

public function getBuildingDistricts()

    {

        return $this->hasMany(BuildingDistrict::className(), ['building_id' => 'id']);

    }



and in my district model:


public function getBuildingDistricts()

    {

        return $this->hasMany(BuildingDistrict::className(), ['district_id' => 'id']);

    }

I want to send Ad information along with it’s building and district information in JSON in an ActiveController. this what I’s doing right now:


$ads = Ad::find()->with('building.buildingDistricts')->all();

        $t = array();

        foreach ($ads as $ad) {

            $t[] = [$ad, $ad->building,$ad->building->buildingDistricts];

        }

        return $t;

Is this the right approach? Is there a way to send the district information in the building entity?

I don’t know your task, so it’s little difficult to advise.

But I noticed 2 things in your code, that you perhaps can improve:

  1. If you have several ajax controllers, that response in json format data from your models - may be it’s better to user REST

http://www.yiiframework.com/doc-2.0/guide-rest-quick-start.html

  1. If you have m:n relation - it’s conveniently to define this relation with hasMany() and viaTable()