ActiveRecord- sql not working correct

Hi, I have relation as below

I create sql


  $place = Room::find()->select(['place.*','room.*', 'seanse.*'])->innerJoinWith(['places','seanses'])->where(['Is_empty'=>0, 'seanse.id_seans'=>$id])->all();

And get


SELECT `place`.*, `room`.*, `seanse`.* FROM `room` INNER JOIN `place` ON `room`.`id_room` = `place`.`id_room` INNER JOIN `seanse` ON `room`.`id_room` = `seanse`.`id_room` WHERE (`Is_empty`=0) AND (`seanse`.`id_seans`='11')

In PHP MY ADMIN this sql query return correctlly value… but on the my site it return all value witchout checking condition "Id_empty=>0"

WHY?

If the sql output is the same that produce Yii (you can check using debug toolbar), you should see same result in phpMyAdmin and website.

Sql can be simplified removing selected fields:




$place = Room::find()->innerJoinWith(['places','seanses'])->where(['Is_empty'=>0, 'seanse.id_seans'=>$id])->all();



Are you sure that sql output of this command is the same that you launch in phpMyAdmin?

Toolbar debug

I removed select column and not working… Is_empty still 1 or 0… if I type e.g 2 for condition Is_empty=>2 it show empty array.

it’s query in phpMyAdmin and his result … correctly


	SELECT `room`.*, place.*FROM `room` INNER JOIN `place` ON `room`.`id_room` = `place`.`id_room` INNER JOIN `seanse` ON `room`.`id_room` = `seanse`.`id_room` WHERE (`Is_empty`=0) AND (`seanse`.`id_seans`='13')

[I added select column only here to show value]

Try with:




$place = Room::find()->innerJoinWith([

'places' => function($q) {

     $q->andWhere(['Is_empty' => 0]);

},

'seanses' => function($q) use($id) {

     $q->andWhere(['seanse.id_seans'=>$id]);

}])->all();



Now I’m seeing that you are using Room model to get Place models.

What do you need? Places or Rooms?

I need Places tables information mainly but I have to Join these three tables. Your code working, but why? can you explein me difference beetwen my query and your ?

If you need places table information, you have to get the data from Place model, so your query should be as:




Place::find()->...



When you use innerJoinWith (http://www.yiiframework.com/doc-2.0/yii-db-activequery.html#innerJoinWith()-detail) Room models are returned that satisfy required joins. Then, it will be loaded related data based on ‘places’ and ‘senses’ relations (defined in the Rool model) on the rooms result models and that relation miss the conditions applied to the joins.

Other these things, the first error is to use Room model to get Place data.

You should start from Place model to get same type data.

Thanks! but i tried like you said and gets error, common\models\place has no relation named "seanses"., I understand why this error, becouse in place model i not have relation with seanse. I generated relation on based database like on the my first screen. So i used Room model to fetch data, becouse he have relation with seanses and place.


 $place = place::find()->innerJoinWith(['idRoom','seanses'])->where(['Is_empty'=>0, 'seanse.id_seans'=>$id])->all();

Seeing the sql executed, I think you need also seanses ‘relation’ in Place:




 $place = Place::find()->innerJoinWith(['seanses'])->where(['Is_empty'=>0, 'seanse.id_seans'=>$id])->all();



Yes, but i can’t everywhere create relation. Look my database relation. I need join 3 tables, place,seanses and room but place not have relation with seanses. How i can do it witchout create artificial relations?

Why i must begin fetch array since Room, becouse he have relation with seanses and place

Sometimes we have some tables who we want join and we can do it in plain sql, but not in Active Record

look my database. If i would like join category, movie and seans i can’t do that becouse i don’t have relation.

In plain sql could be look


SELECT movie.*, seanse.*, category.* from  movie  JOIN category on movie.id_category=category.id_category JOIN seanse on movie.id_movie=seanse.id_movie

Why can’t you join places and seanses using room_id, as you have done in the first sql?




SELECT `place`.*, `room`.*, `seanse`.* FROM `room` INNER JOIN `place` ON `room`.`id_room` = `place`.`id_room` INNER JOIN `seanse` ON `room`.`id_room` = `seanse`.`id_room` WHERE (`Is_empty`=0) AND (`seanse`.`id_seans`='11')



In this query places and seans are joined using id_room field and conditions are applied only to place and seanse, so room is unuseful.

One thing you have to note is:

In the ActiveRecord of Yii 2, the related models are always fetched with a separated query.

For instance:




$users = User::find()->with('posts')->all();



The code above will result in 2 queries:




select * from user;

select * from post where id in ( ... );


-- ( ... ) refers to the user ids fetched in the 1st query.



The 1st query is used to populate the array of main models, while the 2nd query is used to populate the related models. The result set of the 1st query is not used for the related models.

This is also true when you use "joinWith".




$users = User::find()

    ->select(['user.*', 'post.*'])

    ->innerJoinWith('posts')

    ->where(['like', 'post.title', 'yii'])

    ->all();



The code above will result in this:




select user.*, post.* from user inner join post on post.user_id = user.id

    where post.title like '%yii%';

select * from post where id in ( ... );



You may select a column of the joined table in the first query, but note, it is not used to populate the related models. The related models are always fetched with the 2nd query.

As a consequence, while you can select all the users that have at least one post with the title having ‘yii’, but you can not exclude the posts that don’t have ‘yii’ in their title.

In order to filter the related models, you can adjust the relational condition on the fly as @Fabrizio has shown in a previous post.




$users = User::find()

    ->innerJoinWith([

        'posts' => function($q) {

            $q->andWhere(['like', 'post.title', 'yii']);

         },

    ])

    ->all();



This condition will take effect not only for the 1st query but also for the 2nd query, and you’ll get the expected result.




select * from user inner join post on post.user_id = user.id

    and post.title like '%yii%';

select * from post where id in ( ... ) and post.title like '%yii%';



Just have written a wiki on the relational query of Yii 2.0 ActiveRecord.

http://www.yiiframework.com/wiki/834/relational-query-eager-loading-in-yii-2-0/

OK, now I understand! Thanks !