CakePHP - 在单个操作中两次使用paginate()时忽略的条件

时间:2012-03-13 09:39:26

标签: cakephp conditional-statements paginate

我有一个基于CakePHP 2.0构建的photoblog,其数据结构如下:

POSTS <-habtm-> TAGS <-habtm-> IMAGES

我正在构建一个基于AJAX的功能,以查找与给定标记匹配的所有博客帖子和图像。首次选择标签时,第1页的帖子和第1页的图像会被加载到相邻的面板中。之后,他们可以独立分页。在大多数情况下,这工作正常,除非我正在获取初始数据页面。

我在第一个动作中使用paginate()两次 - 一次获取我的帖子,第二次获取图像。问题是我为序列中第二个模型分配给paginate()的条件被完全忽略。单独地,它们都工作正常,并且切换它们的顺序已经证实它对我来说是一个依赖于序列的问题,而不是局限于其中一个模型或其他模型。

我一直在搜索是否有其他人在过去遇到类似的问题,但这对我来说是一个不寻常的设计选择,或者我找不到合适的搜索查询。

我的基本$paginate数组在我的TagsController.php

中声明如下
public $paginate = array(
    "PostsTag" => array(
        "limit" => 4,
        "order" => "Post.id DESC",
        "contain" => array(
            "Tag",
            "Post" => array("fields" => array(
                "id", "title", "created"))
        ),
        "group" => array("Post.id")
    ),
    "ImagesTag" => array(
        "limit" => 4,
        "order" => "Image.id DESC",
        "contain" => array(
            "Tag",
            "Image" => array("fields" => array(
                "id", "title", "url", "created", "gallery"))
        ),
        "group" => array("Image.id")
    )
);

从我的主要搜索操作中,我调用了两个私有函数:

$posts = $this->post_pagination($tagIds);

$images = $this->image_pagination($tagIds);

将限制条件添加到$paginate,如下所示:

private function post_pagination($tags, $page = 1) {
    $this->paginate['PostsTag']['conditions'] = array(
        "status" => 1,
        "OR" => array("tag_id" => $tags)
    );
    $this->paginate['PostsTag']['page'] = $page;
    return $this->paginate("PostsTag");
}

private function image_pagination($tags, $page = 1) {
    $this->paginate['ImagesTag']['conditions'] = array(
        "gallery" => 1,
        "OR" => array("tag_id" => $tags)
    );
    $this->paginate['ImagesTag']['page'] = $page;
    return $this->paginate("ImagesTag");
}

Cake正在尊重limitordercontain等没有问题,但专门针对我尝试分页的模型专门针对conditions。它反馈了我正确订购的前4个结果,但完全未经过滤。我不认为我有点复杂的conditions也有问题 - 只要我不破坏语法,我就可以为第二个conditions输入完全随机的字符串到paginate()并得到返回相同的结果。

非常感谢任何帮助或建议。

[edit]以下是第二个paginate()查询的SQL转储:

SELECT `PostsTag`.`id`, `PostsTag`.`post_id`, `PostsTag`.`tag_id`, 
`Tag`.`id`, `Tag`.`name`, `Post`.`id`, `Post`.`title`, `Post`.`created` 
FROM `posts_tags` AS `PostsTag` 
LEFT JOIN `tags` AS `Tag` ON (`PostsTag`.`tag_id` = `Tag`.`id`) 
LEFT JOIN `posts` AS `Post` ON (`PostsTag`.`post_id` = `Post`.`id`) 
WHERE 1 = 1 
GROUP BY `Post`.`id` 
ORDER BY `Post`.`id` 
DESC LIMIT 4

正如您所看到的,Cake正在生成WHERE 1 = 1来代替我的条件。

2 个答案:

答案 0 :(得分:3)

来自未来的亲人:这是我们到目前为止所发现的......

OP是正确的,YourController::$paginate仅被送入PaginatorComponent一次。如果您需要使用不同的选项再次调用YourController::paginate(),则需要先卸载该组件,例如:

$this->Components->unload('Paginator');

然后,下次您致电YourController::paginate()时,它会重新加载YourController::$paginate属性中的任何内容。

答案 1 :(得分:2)

因此,在更多的讨论中,我发现了以下内容:

在进行初始$paginate通话后对paginate()所做的任何更改都不会传到Paginator组件。这适用于conditionsorderlimit

这样做:

$this->paginate['<model1>']['conditions'] = array( ... );
$model1Results = $this->paginate("<model1>");

$this->paginate['<model2>']['conditions'] = array( ... );
$model2Results = $this->paginate("<model2>");

将返回符合新条件/订单/限制/您应用的任何内容的<model1>的结果,但<model2>的结果将基于$paginate中为其定义的原始条件1}}。您的控制器会看到$paginate的更新就好了,但$paginate Paginator只能被$paginate抓取一次。

我找到的解决方法是在第一次paginate()来电之前对$this->paginate['<model1>']['conditions'] = array( ... ); $this->paginate['<model2>']['conditions'] = array( ... ); $model1Results = $this->paginate('<model1>'); $model2Results = $this->paginate('<model2>'); 进行任何和所有更改,所以:

PaginatorComponent.php

我一直在{{1}}探索,以找出事情的原因,当然,任何进一步的见解都会受到赞赏。