我有一个基于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正在尊重limit
,order
,contain
等没有问题,但专门针对我尝试分页的模型专门针对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
来代替我的条件。
答案 0 :(得分:3)
来自未来的亲人:这是我们到目前为止所发现的......
OP是正确的,YourController::$paginate
仅被送入PaginatorComponent
一次。如果您需要使用不同的选项再次调用YourController::paginate()
,则需要先卸载该组件,例如:
$this->Components->unload('Paginator');
然后,下次您致电YourController::paginate()
时,它会重新加载YourController::$paginate
属性中的任何内容。
答案 1 :(得分:2)
因此,在更多的讨论中,我发现了以下内容:
在进行初始$paginate
通话后对paginate()
所做的任何更改都不会传到Paginator
组件。这适用于conditions
,order
,limit
等
这样做:
$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}}探索,以找出事情的原因,当然,任何进一步的见解都会受到赞赏。