Active Record not returning data of joined table

Yii Framework ist really great, but I encountered a problem when using Active Record for querying data from MySQL database.

When I join 2 tables (‘building’ and ‘building_info’) in my Function “get” in model Building, there will be no data returned from my second table. If I execute the same query with Query Class, rows from both table will be returned. With Active Record I only get data from table ‘building’.

Model Building:




...

// Setting Relation

public function getBuildingInfos()

{

    return $this->hasMany(BuildingInfo::className(), ['BuildingID' => 'ID']);

}    


// Get all buildings

public function get() {

    $building = Building::find()

        ->joinWith('buildingInfos')

        ->where(['building_info.langID' => 1])

        ->all();


    return $building;

}

// Attributes

public function attributeLabels()

{

    return [

        'ID' => 'ID',

        'NameBreak' => 'Name Break',

        'Tileset' => 'Tileset',

        'TilesetPosition' => 'Tileset Position',

        ...

    ]

}

...



Model BuildingInfo:




...

public function attributeLabels()

{

    return [

        'buInfoID' => 'Bu Info ID',

        'BuildingID' => 'Building ID',

        'langID' => 'Lang ID',

        'Name' => 'Name',

        'ShortDesc' => 'Short Desc',

        'ShortDescDisabled' => 'Short Desc Disabled',

    ];

} 

public function getBuilding()

{

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

}

...



Do you know how to solve this problem?

Thanks Sven

Hi Blues1ght, welcome to the forum.

Your “buildingInfos” relation should return an array of BuildingInfo models. Do you say that ‘$building->buindingInfos’ is an empty array?

Hi softark,

Thank you for your quick reply :)

If I try to get $building->buildingInfos, an error appears saying that $building is not an object (‘Trying to get property of non-object’).

But it has no affect, if I create an object first ($building = new Building())

Would you please show your code that calls this function?

Of course… here it is:

Controller (GameController.php), I call this Controller by AJAX Request




class GameController extends Controller

{

    ...

    public function actionBuilding()

    {

       $building = new Building();

       $buildings = $building->get();        

        

       Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;     

       return $buildings;

    }

    ...

}



As I mentioned above, If I execute the select statement including left join with the DB\Query Class, then the related data will be returned (but all data types lost):




...

MoneyCost: "500"

Name: "Vogtei I"

NameBreak: "0"

NeededBuildingID: "0"

NeededResearchID: "0"

NeedsStreet: "1"

...



But I would like to get the related with Active Record (data of second table is missing here):




...

MoneyCost: 500

NameBreak: 0

NeededBuildingID: 0

NeededResearchID: 0

NeedsStreet: 1

...



Thanks.

First, check to see if the relations are properly populated.




       $building = new Building();

       $buildings = $building->get();        

       

       // check

       foreach($bulidlings as $<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' /> {

            print_r($<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' />;

            print_r($b->buildingInfos);

       }

 

       Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;     

       return $buildings;



Your code assumes that an implicit conversion of an ActiveRecord object to an array. I wonder if it’s possible or not.

This is the answer I get. It seems like it’s there, but it’s getting lost, when I return it?




app\models\Building Object

(

    [_attributes:yii\db\BaseActiveRecord:private] => Array

        (

            [ID] => 1

            [NameBreak] => 0

            [Tileset] => public001_192x192

            [TilesetPosition] => Floor

            [TilesetPositionUniqueType] => 

            [Width] => 192

            [Height] => 192

            [gx] => 3

            [gy] => 3

            [OffsetX] => -64

            [bgleft] => 0

            [bgtop] => 0

            [Rotation] => 4

            [MenuColumn] => 1

            [Sort] => 1

            [BuildmenuVisible] => 1

            [UniqueBuilding] => 1

            [IconPath] => icon_set001

            [IconLeft] => 0

            [IconTop] => 0

            [MenuTemplate] => none

            [MoneyCost] => 500

            [IngameCurrencyCost] => 0

            [BuiltTime] => 0

            [Scaffold] => 1

            [LumberCost] => 10

            [ToolCost] => 10

            [StoneCost] => 0

            [BrickCost] => 0

            [RoofingTileCost] => 0

            [MarbleCost] => 0

            [GlassCost] => 0

            [OrnamentCost] => 0

            [PalinCost] => 0

            [ResidentLvLNeeded] => 0

            [ResidentNeeded] => 0

            [NeededBuildingID] => 0

            [NeededResearchID] => 0

            [BuildingLvL] => 1

            [BuildingType] => 1

            [BuildingEfc] => 0

            [BuildingSfx] => 0

            [BuildEfc] => 0

            [BuildSfx] => 0

            [DestroyEfc] => 0

            [DestroySfx] => 0

            [NeedsStreet] => 1

            [WaterSource] => 0

            [MaxHitpoints] => 5000

            [MinHitpoints] => 200

            [Invulnerable] => 0

            [InfluenceRadiusPublic] => 30

            [InfluenceRadiusProduction] => 0

            [InfluenceRadiusMilitary] => 15

            [InfluenceRadiusTypeNeeded] => none

            [InfluenceRadius] => 30

            [InfluenceIDNeeded] => 0

            [ActiveCost] => 20

            [InactiveCost] => 20

            [CarrierCount] => 0

            [CarrierID] => 0

            [FarmfieldCount] => 0

            [FarmfieldID] => 0

            [FarmfieldTolerance] => 0

            [FertilityNeeded] => 

            [MinResidentCount] => 1

            [MaxResidentCount] => 10

            [DowngradeID] => 0

            [UpgradeID] => 2

            [Storage] => 30

            [MilitarySlots] => 12

        )


    [_oldAttributes:yii\db\BaseActiveRecord:private] => Array

        (

            [ID] => 1

            [NameBreak] => 0

            [Tileset] => public001_192x192

            [TilesetPosition] => Floor

            [TilesetPositionUniqueType] => 

            [Width] => 192

            [Height] => 192

            [gx] => 3

            [gy] => 3

            [OffsetX] => -64

            [bgleft] => 0

            [bgtop] => 0

            [Rotation] => 4

            [MenuColumn] => 1

            [Sort] => 1

            [BuildmenuVisible] => 1

            [UniqueBuilding] => 1

            [IconPath] => icon_set001

            [IconLeft] => 0

            [IconTop] => 0

            [MenuTemplate] => none

            [MoneyCost] => 500

            [IngameCurrencyCost] => 0

            [BuiltTime] => 0

            [Scaffold] => 1

            [LumberCost] => 10

            [ToolCost] => 10

            [StoneCost] => 0

            [BrickCost] => 0

            [RoofingTileCost] => 0

            [MarbleCost] => 0

            [GlassCost] => 0

            [OrnamentCost] => 0

            [PalinCost] => 0

            [ResidentLvLNeeded] => 0

            [ResidentNeeded] => 0

            [NeededBuildingID] => 0

            [NeededResearchID] => 0

            [BuildingLvL] => 1

            [BuildingType] => 1

            [BuildingEfc] => 0

            [BuildingSfx] => 0

            [BuildEfc] => 0

            [BuildSfx] => 0

            [DestroyEfc] => 0

            [DestroySfx] => 0

            [NeedsStreet] => 1

            [WaterSource] => 0

            [MaxHitpoints] => 5000

            [MinHitpoints] => 200

            [Invulnerable] => 0

            [InfluenceRadiusPublic] => 30

            [InfluenceRadiusProduction] => 0

            [InfluenceRadiusMilitary] => 15

            [InfluenceRadiusTypeNeeded] => none

            [InfluenceRadius] => 30

            [InfluenceIDNeeded] => 0

            [ActiveCost] => 20

            [InactiveCost] => 20

            [CarrierCount] => 0

            [CarrierID] => 0

            [FarmfieldCount] => 0

            [FarmfieldID] => 0

            [FarmfieldTolerance] => 0

            [FertilityNeeded] => 

            [MinResidentCount] => 1

            [MaxResidentCount] => 10

            [DowngradeID] => 0

            [UpgradeID] => 2

            [Storage] => 30

            [MilitarySlots] => 12

        )


    [_related:yii\db\BaseActiveRecord:private] => Array

        (

            [buildingInfos] => Array

                (

                    [0] => app\models\BuildingInfo Object

                        (

                            [_attributes:yii\db\BaseActiveRecord:private] => Array

                                (

                                    [buInfoID] => 1

                                    [BuildingID] => 1

                                    [langID] => 1

                                    [Name] => Vogtei I

                                    [ShortDesc] => Erstellt den ersten Baubereich.<br>Gründet Siedlung.<br>Nur eine Vogtei pro Insel möglich.

                                    [ShortDescDisabled] => 

                                )


                            [_oldAttributes:yii\db\BaseActiveRecord:private] => Array

                                (

                                    [buInfoID] => 1

                                    [BuildingID] => 1

                                    [langID] => 1

                                    [Name] => Vogtei I

                                    [ShortDesc] => Erstellt den ersten Baubereich.<br>Gründet Siedlung.<br>Nur eine Vogtei pro Insel möglich.

                                    [ShortDescDisabled] => 

                                )


                            [_related:yii\db\BaseActiveRecord:private] => Array

                                (

                                )


                            [_errors:yii\base\Model:private] => 

                            [_validators:yii\base\Model:private] => 

                            [_scenario:yii\base\Model:private] => default

                            [_events:yii\base\Component:private] => Array

                                (

                                )


                            [_behaviors:yii\base\Component:private] => Array

                                (

                                )


                        )


                )


        )


    [_errors:yii\base\Model:private] => 

    [_validators:yii\base\Model:private] => 

    [_scenario:yii\base\Model:private] => default

    [_events:yii\base\Component:private] => Array

        (

        )


    [_behaviors:yii\base\Component:private] => Array

        (

        )


)

Array

(

    [0] => app\models\BuildingInfo Object

        (

            [_attributes:yii\db\BaseActiveRecord:private] => Array

                (

                    [buInfoID] => 1

                    [BuildingID] => 1

                    [langID] => 1

                    [Name] => Vogtei I

                    [ShortDesc] => Erstellt den ersten Baubereich.<br>Gründet Siedlung.<br>Nur eine Vogtei pro Insel möglich.

                    [ShortDescDisabled] => 

                )


            [_oldAttributes:yii\db\BaseActiveRecord:private] => Array

                (

                    [buInfoID] => 1

                    [BuildingID] => 1

                    [langID] => 1

                    [Name] => Vogtei I

                    [ShortDesc] => Erstellt den ersten Baubereich.<br>Gründet Siedlung.<br>Nur eine Vogtei pro Insel möglich.

                    [ShortDescDisabled] => 

                )


            [_related:yii\db\BaseActiveRecord:private] => Array

                (

                )


            [_errors:yii\base\Model:private] => 

            [_validators:yii\base\Model:private] => 

            [_scenario:yii\base\Model:private] => default

            [_events:yii\base\Component:private] => Array

                (

                )


            [_behaviors:yii\base\Component:private] => Array

                (

                )


        )


)



Probably you have to convert each ActiveRecord object to an associative array before you return the results.

The following is a rough understanding of mine regarding the JSON formatting in the response.

When the response format is JSON and the content of it is not specified yet, the response component will try to convert the data into a JSON string using Json:encode(). Basically it will do so by serializing an associative array to a string. When given an object instead of an array, it will try to convert the object to an array when the object is arrayable. A Model is arrayable, so the ordinary attributes are converted into the elements of an array. But, the relations are not arrayable, I guess. That’s why you don’t get the relational data in the final output of JSON.

Please make a correction if I’m wrong > @anyone who has a clear understanding regarding this.

Well, in my opinion your explanation is the only one which makes sense for me too. So I tried this approach and it works so far:




       foreach($buildings as $<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='B)' /> {


            $temp = array(

                "Building" => $B,

                "BuildingInfo" => $B->buildingInfos

            );

            $build[] = $temp;

       } 



So in the end i have an array of objects with an Object (Building) and an array (buildingInfo). I don’t think there is another way? :)

Thanks for your help. I really appreciate it!

just add asArray()

    $building = Building::find()

        ->joinWith('buildingInfos')
        ->assArray()

        ->where(['building_info.langID' => 1])

        ->all();


    return $building;