Showing data from 2 models in a grid with Yii
I'm trying to select data from two tables and show that data in a paginated grid view. The problem is that Yii is joining the data with a SQL join (because I told it to do it) and because of that it's not showing the correct number of items per page.
To make in clear, I'm selecting from topics
and messages_in_topics
, and I'm joining then with
$criteria->together = true;
This makes MySQL to return a row for each message (and the related topics). Example:
id_topic topic id_messages message
1 topic1 1 message1_in_topic1
1 topic1 2 message2_in_topic1
1 topic1 3 message3_in_topic1
2 topic2 4 message1_in_topic2
2 topic2 5 message2_in_topic2
There are only 2 topics, but Yii's paginator thinks there are 5.
The fastest way to "fix" this is grouping by the id_topic field, anyways, I can't do that because there's a where condition which searches with the like
statement.
Thank you
EDIT:
Here's my action code:
$criteria = new CDbCriteria;
$get_s = Yii::app()->request->getQuery('s', '');
if( $get_s ){
$criteria->compare("topic_title", $get_s, true);
$criteria->compare("message_text", $get_s, true, 'OR');
}
$criteria->with = array('messages');
$criteria->addCondition(array( ...... )); <--- some rules like if the topic is validated...
$dataProvider = new CActiveDataProvider('Topics', array(
'criteria'=>$criteria,
'pagination=>array('pageSize'=>15)
));
Actually, what happens there is that the information being displayed is in regard to your messages. The repeated topic values are because these topics are the corresponding related data to the message.
You could try to tell your query to use GROUP BY in the results...
SELECT t.id_topic, t.topic, COUNT(m.id_messages)
FROM topics t LEFT JOIN messages m ON t.id_topic = m.id_topic
GROUP BY t.id_topic
This way, more or less, you can display the count of messages-per-topic. I could help you more if you'd show us your SQL.
EDIT : After seeing your code, here is my guess: $criteria = new CDbCriteria;
$get_s = Yii::app()->request->getQuery('s', '');
if( $get_s ){
$criteria->compare("topic_title", $get_s, true);
$criteria->compare("message_text", $get_s, true, 'OR');
}
$criteria->with = array('messages');
$criteria->addCondition(array( ...... )); <--- some rules like if the topic is validated...
$dataProvider = new CActiveDataProvider('Topics', array(
'criteria'=>$criteria,
'pagination=>array('pageSize'=>15)
));
You can make sure the query isn't complicated by yii's formatting by pouring it using only three basic properties of CDbCriteria:
Also, You can also make sure to set these properties directly, so you actually descompose your query into the CDbCriteria object. For instance:
SELECT t.id_topic, t.topic, COUNT(m.id_messages)
FROM topics t LEFT JOIN messages m ON t.id_topic = m.id_topic
GROUP BY t.id_topic
would be like this
/*1*/ $criteria->select = 't.id_topic, t.topic, COUNT(m.id_messages)';
/*2*/ $criteria->condition = 't.topic_title LIKE %'.$get_s.'% OR ...';/* add your conditions here*/
/*3*/ $criteria->join = 'LEFT JOIN messages m ON t.id_topic = m.id_topic'; //Full join statement here, including the nature of the join.
/*4*/ $criteria->group = 't.id_topic';
IMPORTANT : take into account that since you pass your Topics
classname to the CActiveDataProvider
constructor, the table under Topics
will be known as t
. Any other tables must be specified as well (Pretty much like messages m
or messages AS m
)in the join condition otherwise you might get a column xxxx is ambiguous
warning.
Don't pass out the chance of giving an eye to CDbCriteria and CActiveDataProvider for any questions you might have.
The problem isn't the paginator, it is you query. If you run the query:
SELECT *
FROM topics as t
INNER JOIN messages_in_topics as mt
ON mt.topics_id = t.id
INNER JOIN messages as m
ON m.id = mt.messages_id
You will get 5 results, as show in your example above.
So more importantly, what are you trying to do?
Also, your table shows a MANY_MANY relationship (message1 has 2 topics, topic1 has 3 messages), is your database set up the right way, and are your model relations configured accordingly?
Are you trying to show ALL messages in each topic on a single line?
Are you trying to show ALL topics and list each message with that topic?
Assuming you have relations set up correctly, you can just use: $messages=$topics->messages;
and get an array with all the messages listed.
Conversely, you can do $topics=$messages->topics;
to get the topics.
上一篇: YII中的SQL错误::: SQLSTATE [42000]:语法错误或访问冲突:1064
下一篇: 使用Yii显示来自2个模型的数据