4

我正在使用 CakePHP 2.3 开发一个应用程序并且遇到了分页问题。当我单击任何分页链接时,我在此服务器上找不到 /cab/ServiceDirectory/refine/page:2 (或任何链接)。如果我去 /cab/ServiceDirectory/refine 我看到分页链接显示应该有 5 页。如果我从控制器和视图中删除分页代码,我会看到我应该看到的所有结果。

在我的 ServiceDirectoryResultsController 我有

public function index() {
  $this->ServiceLocation->recursive=0;
}

public function refine ($id=null) (

 // All my code to get the ServiceLocations from the DB

$this->paginate->array(
  'conditions' => array('ServiceLocation.state' => $states[$state], 'ServiceLocation.solution_categories' => $active_cat),
  'limit' => 8,
);

$results = $this->paginate('ServiceLocation');
$this->set('serviceLocation' ,$results);

}

在我看来我有

<div class="paging">
  <?php
    echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));
    echo $this->Paginator->numbers(array('separator' => ''));
    echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled'));
  ?>
</div>

<?php foreach ($serviceLocation as $Location): ?>

  // I echo a few things from the $Location array

<?php endforeach; ?>

<div class="paging">
  <?php
    echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));
    echo $this->Paginator->numbers(array('separator' => ''));
    echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled'));
  ?>
</div>

如果没有分页并使用查找全部并将其发送到视图,我会看到我期望的 40 个结果。

随着分页,我看到分页链接,如果我将鼠标悬停在它们上面,我会看到我的网址 /cab/ServiceDirectoryResults/refine/page:2 或 page:3 或 page:4 或 page:5

如果我单击其中任何一个带有 :pageX 的链接,我会收到错误消息

错误:请求的地址“/cab/ServiceDirectoryResults/refine/page:2 在此服务器上找不到”

我已经阅读了大量有关 CakePHP 分页的内容,但找不到任何导致这种行为的原因。任何人都可以提出一个原因或可能的解决方案或可遵循的路径来调试此错误吗?

问候

理查德

我检查了错误级别,它已经​​设置为 2 级

这是错误日志中的最后一个条目

2013-05-22 17:09:28 Error: [NotFoundException] Not Found
Request URL: /cab/ServiceDirectoryResults/refine/page:2
Stack Trace:
#0 /var/www/html/cab/lib/Cake/Controller/Controller.php(1074): PaginatorComponent->paginate('ServiceLocation', Array, Array)
#1 /var/www/html/cab/app/Controller/ServiceDirectoryResultsController.php(381): Controller->paginate('ServiceLocation')
#2 [internal function]: ServiceDirectoryResultsController->refine()
#3 /var/www/html/cab/lib/Cake/Controller/Controller.php(486): ReflectionMethod->invokeArgs(Object(ServiceDirectoryResultsController), Array)
#4 /var/www/html/cab/lib/Cake/Routing/Dispatcher.php(187): Controller->invokeAction(Object(CakeRequest))
#5 /var/www/html/cab/lib/Cake/Routing/Dispatcher.php(162): Dispatcher->_invoke(Object(ServiceDirectoryResultsController), Object(CakeRequest), Object(CakeResponse))
#6 /var/www/html/cab/app/webroot/index.php(109): Dispatcher-   >dispatch(Object(CakeRequest), Object(CakeResponse))
#7 {main}

希望有帮助

4

3 回答 3

6

仅供参考:我使用的是 Cakephp 2.4,我只在这个版本上测试过。

我遇到了同样的问题。我将分页变量存储在用户的会话中。
这样,当用户离开页面时,他们不会在返回页面时失去他们的位置(页面/排序字段/方向)。

因为我将变量存储在会话中,然后从会话中检索它们,如果说用户单击导致结果小于他们所在页面的链接,我将得到 404。

示例(他们所在的页面):
http://localhost/products/index/page:5/sort:Product.name

我把这个链接发给他们:
http://localhost/products/index/search:[search_term]

这会将结果过滤到仅 2 页。
在这种情况下,恢复会话变量的实际(永久)链接将如下所示:
http://localhost/products/index/page:5/sort:Product.name/search:[search_term]

第 5 页超出了新结果的 2 页范围。
这将抛出NotFoundException();这里看到的:http:
//api.cakephp.org/2.4/source-class-PaginatorComponent.html#238

我解决这个问题的方法是捕获异常,然后将它们重定向到第一页。由于所有的分页变量(包括“搜索”)都存储在会话中,我只需要传递页面变量:

例子:
http://localhost/products/index/page:1

Cakephp 推荐这是一种可能的方法来克服它:
http ://book.cakephp.org/2.0/en/core-libraries/components/pagination.html#out-of-range-page-requests

但是,我希望它可用于我所有的“索引”页面,所以我覆盖Controller::paginate()AppController.
在这里看到的原始分页方法:http:
//api.cakephp.org/2.4/source-class-Controller.html#1070-1081

这是我在Controller/AppController.php中的操作方式:

<?php

class CommonAppController extends Controller
{
    // ..... other code
    public function paginate($object = null, $scope = array(), $whitelist = array())
    {
    /*
     * Used to see if we get an exception thrown, 
     * If so, send them to the first page, and set the flash so they know
     */
        try
        {
            // taken from their current paginate();
            // http://api.cakephp.org/2.4/source-class-Controller.html#1070-1081
            return $this->Components->load('Paginator', $this->paginate)->paginate($object, $scope, $whitelist);
        }
        catch (NotFoundException $e)
        {
            //Do something here like redirecting to first or last page.
            //$this->request->params['paging'] will give you required info.
            $page = (isset($this->request->params['named']['page'])?$this->request->params['named']['page']:1);

            $this->Session->setFlash(__('Unable to find results on page: %s. Redirected you to page 1.', $page));
            return $this->redirect(array('page' => 1));
        }
    }
    // ..... other code
}
?>
于 2014-09-16T19:28:09.973 回答
0

8 个月后......我刚刚遇到了同样的问题,并认为我可以将我的发现留在这里,以避免其他人像我一样花费几个小时寻找解决方案。

我遇到了与 Richard 相同的问题,当对分页拆分栏的任何其他链接(从 2 到 n)的 GET 请求生成 404 错误时。此 404 错误源自 PaginatorComponent (CORE/Cake/Controller/Component/PaginatorComponent.php),在这些行中:

$pageCount = intval(ceil($count / $limit));
$requestedPage = $page;
$page = max(min($page, $pageCount), 1);

if ($requestedPage > $page) {
  throw new NotFoundException();
}

简而言之,当谓词条件成员变得如此严格以至于创建的记录集比第 #1 页要小得多时,就会发生这种情况。

可以创建它的是它现在包含更多您不想要的谓词。查看它包含的页面 #2+ 的一种方法是添加此调用:

FirePHP($parameters);

就在上面的行之前。你可能会感到惊讶。

问题是“为什么你应该在控制器中构建并传递给 find() 方法的条件从有效的第 1 页到无效的第 2 页改变了这么多?我不​​能只为你回答没有看到你的其余代码,但我可以告诉你我的情况发生了什么:我在 $_SESSION 中存储了一些值以便可以记住我的搜索,并且我依赖 isset($this->request-> data[$objectName]) 知道我是否应该将该特定谓词添加到我的“条件”数组中。但那是没有想到只有第 1 页POST 方法的结果,而不是随后的分页请求页面通过GET方法。因此,从第 2 页开始,$this->request->data[$objectName] 为空,但 SESSION 仍然设置,因为我忘记重置它。

结论是:记住页面 #2+ 调用是 GET,并且您可能已经使用并正在为 POST 工作的请求数据不再有效,现在创建一组不同的条件,减少您的记录集,并创建一个总数可能为 0,使分页系统无效,因此为 404。

于 2014-01-23T10:05:53.753 回答
0

我遇到了 CakePHP3 的同样问题。最快的解决方法是更改​​表单操作,使其不抓取 URL 的“?page=x”部分。例如,将其更改为当前页面 URL,如

<form action="<?=\Cake\Core\Configure::::read('App.domain')?>/page_url" ...
于 2016-05-27T16:02:22.517 回答