CakePHP - условия, игнорируемые при использовании paginate () дважды в одном действии - PullRequest
0 голосов
/ 13 марта 2012

У меня есть фотоблог, построенный на CakePHP 2.0 со структурой данных, которая выглядит следующим образом:

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");
}

Торт уважает limit, order, contain и т. Д. Без проблем, но бросает мяч на conditions специально для любой модели, которую я пытаюсь разбить на страницы в течение секунды.Он возвращает мне первые 4 результата, упорядоченных должным образом, но полностью не отфильтрованных.Я не думаю, что мои несколько сложные conditions тоже виноваты - пока я не нарушу синтаксис, я могу набирать в conditions совершенно случайные строки для второго paginate() и получать идентичные результаты.

Любая помощь или предложения приветствуются.

[править] Вот дамп SQL второго paginate() запроса:

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 ]

3 голосов
/ 24 октября 2012

УВАЖАЕМЫЕ ЛЮДИ ИЗ БУДУЩЕГО: Вот что мы выяснили до сих пор ...

ОП правильно, что YourController::$paginate подается в PaginatorComponent только один раз.Если вам нужно снова вызвать YourController::paginate() с другими вариантами, сначала вам нужно выгрузить компонент, например:

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

Затем, при следующем вызове YourController::paginate(), он перезагрузит все, что находится вYourController::$paginate свойство.

2 голосов
/ 16 марта 2012

Итак, после еще одного осмотра я обнаружил следующее:

Любые изменения, внесенные в $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>, которые подчиняются новым условиям / порядку/ limit / что бы вы ни применяли, но ваши результаты для <model2> будут основаны на исходных условиях, определенных для него в $paginate.Ваш контроллер будет видеть обновления $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, чтобы выяснить, почему все работает таким образом, и любое дальнейшее понимание, конечно, будет оценено.

...