简体   繁体   English

使用 Yii 在网格中显示来自 2 个模型的数据

[英]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.问题是 Yii 使用 SQL 连接来连接数据(因为我告诉它这样做),因此它没有显示每页正确的项目数。

To make in clear, I'm selecting from topics and messages_in_topics , and I'm joining then with为了清楚起见,我正在从topicsmessages_in_topics选择,然后我将加入

$criteria->together = true;

This makes MySQL to return a row for each message (and the related topics).这使得 MySQL 为每条消息(和相关主题)返回一行。 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.只有 2 个主题,但 Yii 的分页器认为有 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. “修复”这个问题的最快方法是按 id_topic 字段分组,无论如何,我不能这样做,因为有一个 where 条件使用like语句进行搜索。

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...您可以尝试告诉您的查询在结果中使用 GROUP BY ...

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.如果您向我们展示您的 SQL,我可以为您提供更多帮助。

EDIT : After seeing your code, here is my guess: $criteria = new CDbCriteria;编辑:看到你的代码后,这是我的猜测: $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:您可以通过仅使用 CDbCriteria 的三个基本属性倾倒查询来确保查询不会被 yii 的格式复杂化:

  1. $criteria->select is exactly the list of columns you want to select. $criteria->select正是您要选择的列列表。
  2. $criteria->condition is exactly the WHERE condition, I honestly prefer using a string to an array, since using the string allows me to use the exact condition I put in here. $criteria->condition正是 WHERE 条件,老实说,我更喜欢使用字符串而不是数组,因为使用字符串允许我使用我在这里输入的确切条件。
  3. $criteria->join is attached immediately after the $model->tableName() you specify in the CActiveDataProvider constructor. $criteria->join紧接在您在 CActiveDataProvider 构造函数中指定的 $model->tableName() 之后。
  4. $criteria->group is added at the end of the query, you just need to specify the grouping column. $criteria->group添加在查询的最后,你只需要指定分组列。

Also, You can also make sure to set these properties directly, so you actually descompose your query into the CDbCriteria object.此外,您还可以确保直接设置这些属性,这样您实际上将查询分解为 CDbCriteria 对象。 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 .重要提示:考虑到由于您将Topics类名传递给CActiveDataProvider构造函数, Topics下的表将被称为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.还必须在连接条件中指定任何其他表(非常类似于messages mmessages AS m ),否则您可能会收到column xxxx is ambiguous警告。

Don't pass out the chance of giving an eye to CDbCriteria and CActiveDataProvider for any questions you might have.对于您可能遇到的任何问题,不要错过关注CDbCriteriaCActiveDataProvider的机会。

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.您将获得 5 个结果,如上面的示例所示。

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?此外,您的表显示了 MANY_MANY 关系(message1 有 2 个主题,topic1 有 3 个消息),您的数据库设置是否正确,您的模型关系是否相应配置?

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;假设你的关系设置正确,你可以使用: $messages=$topics->messages; and get an array with all the messages listed.并获取一个包含所有列出的消息的数组。

Conversely, you can do $topics=$messages->topics;相反,您可以执行$topics=$messages->topics; to get the topics.获取主题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM