CakePHP 2分页给出404地址未找到错误

时间:2013-05-22 06:12:00

标签: cakephp pagination runtime-error

我正在使用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个结果。

随着分页我看到分页链接,如果我将鼠标悬停在它们上面,我会看到我的url / 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}

希望有所帮助

3 个答案:

答案 0 :(得分:5)

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

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

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

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

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

这会将结果过滤为2页  在这种情况下,恢复会话变量的实际(perma)链接看起来像:
    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

我如何解决这个问题是为了捕获异常,然后将它们重定向到第一页。 由于所有分页变量(包括&#39; search&#39;)都存储在会话中,我只需要传递页面变量:

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

Cakephp建议将其作为克服它的可行方法:
    http://book.cakephp.org/2.0/en/core-libraries/components/pagination.html#out-of-range-page-requests

但是,我希望这适用于我的所有索引&#39;页面,所以我覆盖了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
}
?>

答案 1 :(得分:0)

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

我遇到了与理查德相同的问题,当对分页分隔栏的任何其他链接(从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-&gt; request-&gt; data [$ objectName])来知道我是否应该将该特定谓词添加到我的''条件阵列。但是,没想到只有第1页 POST方法的结果,而不是后续的分页请求页面,这些页面通过 GET 方法。因此,从第2页开始,$ this-&gt; request-&gt; data [$ objectName]为空,但SESSION仍然设置,因为我忘记重置它。

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

答案 2 :(得分:0)

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

<form action="<?=\Cake\Core\Configure::::read('App.domain')?>/page_url" ...