复杂的CakePHP数据返回并组合

时间:2011-09-04 13:27:50

标签: php arrays cakephp sql-order-by

我的目标是在我正在处理的应用程序上创建活动的摘要页面。我已经确定我必须做以下事情:

从我订阅的人那里获取所有故事,并将其格式化如下:

[Username] has posted [StoryName] - View story

获取与我关联的用户发布的评论的所有故事

[Username] has posted a comment on [StoryName] - View story

我不确定如何获得两个数组,显示我想要的格式,但是按照发布日期排序(与人们喜欢Facebook一样)

最好的方法是什么?

请注意:答案必须是易于扩展的内容。我正在考虑关注wordpress'模型并创建一个Posts表,其中有一个Post Type字段。

4 个答案:

答案 0 :(得分:4)

您尝试做的事情几乎与CakePHP内置。最重要的是确保您的模型正确关联。一旦完成,Cake将为您完成大部分繁重的工作。

根据您的情况,使用以下相关的3个模型:

class Story extends AppModel{
    var $belongsTo = 'Author';
    var $hasMany = 'Comment';
}

class Author extends AppModel{
    var $hasMany = array( 'Story', 'Comment' );
    var $hasAndBelongsToMany = 'User';
}

class Comment extends AppModel{
    var $belongsTo = array( 'Author', 'Story' );
}

根据Cake约定设置表。然后你的控制器中有一点CakePHP魔法:

$this->Story->Author->bindModel( array( 'hasOne' => array( 'AuthorsUsers' ) ) );
$myAuthors = $this->Story->Author->find( 'list', array(
    'fields' => array( 'id' ),
    'conditions' => array( 'AuthorsUsers.user_id' => $userId ),
    'recursive' => false 
    ) );

$stories = $this->Story->find( 'all', array(
    'fields' => array( 'Story.id', 'Story.title', 'Author.id', 'Author.name' ),
    'order' => 'published_date DESC',
    'conditions' => array( 'Author.id' => $myAuthors ),
    'recursive' => 2
    ) );

快速解释发生了什么:

  • bindModel()让Cake知道您希望使用HABTM关联按相关用户ID查找作者。 (Cake约定是有一个名为'authors_users'的表来加入Author-> User HABTM关联。)
  • 如果您调试$myAuthors变量,您会看到它得到一个简单的ID数组。
  • 'conditions' => array( 'field' => array() )将被解析为“WHERE字段IN(...)”。在此示例中,我们获取所有模型WHERE 'Author.id' IN $myAuthors
  • 简短的$this->Story->find()电话是蛋糕之美。它将自动查找符合指定条件的所有Story模型,它将找到与每个找到的Story相关联的其他模型。 (您可以通过关闭Recursive或使用Containable行为来告诉它不要找到关联的模型。)
  • 调试$stories变量将显示如下结构:
Array
(
    [0] => Array
        (
            [Story] => Array
                (
                    [id] => 1
                    [title] => 'Common Sense'
                    [published_date] => 1776-01-10 
                )
            [Author] => Array
                (
                    [id] => 1
                    [name] => 'Thomas Paine'
                )
            [Comment] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [text] => 'Revolutionary!'
                            [Author] => Array
                                (
                                    [id] => 3
                                    [name] => 'Silence Dogood'
                                )
                        )
                    [1...n] => ...
                )
        )
    [1...n] => ...
)

然后,您可以在视图中使用该结构来根据需要显示数据。

我觉得应该有一种方法只用1个查询来实现它,但这种方式有效,并且不需要你做任何子查询或在Cake find()调用中插入自定义SQL。

答案 1 :(得分:0)

Gary,如果不了解你的模特,很难回答这个问题。假设您已经正确定义了架构和模型,那么它应该相对容易。

为查找查询按日期DESC排序并检索最后10行。 (例如,这会给你最后20个结果)

将结果集合并为一个并再次按日期DESC排序。然后,根据需要渲染字符串是一些简单的渲染逻辑。

答案 2 :(得分:0)

好吧,我会做这样的事情

创建以下关系

用户 hasMany StoryName

用户 hasMany 评论

StoryName hasMany 评论

评论 belongsTo 用户

评论 belongsTo StoryName

这样可以很容易地检索所需的所有信息,因为您可以通过用户模型获取所有需要的数据,例如

$this->User->recursive = 2;

$this->User->find('all', $params) *// on $params you could use the conditions that the user retrieved should be friends to the current user*

希望这会给我一个填充了以下结构的数组

[USER]   [帖子]   [COMMENTS]

只是将它传递给视图并在视图中使用foreach来创建Html

答案 3 :(得分:0)

我不知道您是否已经安装了其他型号(用户,故事等)。但为了保持答案,我将只关注活动模型(活动表):您可以像使用日志表一样使用此表。

一个简单的表:id,user_id,story_id,created(datetime),action_type(0表示故事,1表示对故事的评论)。然后,只需查询此表即可查找活动。

或者更通用的,可扩展的:id,subject_id,subject_type(用户或其他任何行为),verb_type,object_id,object_type,created。您不必将此模型绑定到任何其他模型(尽管您可以在指定关系时使用'conditions')或者动态绑定bindModel。