【发布时间】:2012-11-26 18:39:59
【问题描述】:
我的网站有很多“页面”。页面针对不同的主题创建并由用户管理(例如,加勒比海盗页面或贾斯汀比伯页面)。该页面属于一个类别,例如电影或音乐。页面的默认 URL 是 http://www.example.com/category-directory/page-id。或者,如果版主想要建立自己的页面链接作为更简单的导航方式,他们可以通过为“Page.link”列赋予值来实现(例如:电影 Pirates 的 http://www.example.com/potc加勒比地区)。
我的路线都设置好了,这本身就需要一些时间。该路由检查“.com”之后的 URL 的第一个参数是否与任何页面的“链接”列匹配,如果匹配,则路由到该页面及其下的控制器/操作。如果没有,照常路线。
当用户查看http://www.example.com/potc/articles/99 或http://www.example.com/movies/106/articles/99 时(假设加勒比海盗 是id = 106 的页面),然后用户被定向到文章控制器,查看操作, id = 99. 106 作为 $page_id 传递给控制器的操作,并在 AppController 中设置。
我在控制器中提供的 URL 数组可以正常工作,例如,如果 id 不存在,我会重定向到 'controller' => 'articles', 'action' => 'index', 'page_id' = $page_id。我被重定向回http://www.example.com/potc/articles。我实际上不必定义控制器,因为默认情况下它使用当前控制器。
但是,我遇到了分页链接问题。例如,我在文章索引页面上,有 100 篇文章,但我只查看前 20 篇。我希望将 URL 输出为http://www.example.com/potc/articles/page:2。
相反,如果我将 URL 数组设置为 'controller' => 'articles', 'action' => 'index', 'page_id' => $page_id,类似于我在控制器中所做的,我会得到链接 http://www.example.com/articles/page_id:106/page:2,我可以理解为什么这条路线不起作用,因为我可能必须传递值 Page。如果存在则链接,如果不传递 Category.directory 和 Page.id。我尝试使用 URL 数组 'controller' => 'articles', 'action' => 'index', 'category' => $page['Category']['directory'], 'page_id' => $page_id 执行后一个选项。我有一条与之匹配的路线,但分页链接仍然生成为http://www.example.com/articles/category:movies/page_id:106/page:2
这是我的 routes.php 中的一些 sn-ps:https://gist.github.com/9ba0a54a7f4d68803d14
我的问题是:“我可以使用准确的当前 URL 进行分页链接(减去对我所在的当前页面的引用)吗?”例如,如果我正在查看 http://www.example.com/dynamic-route/controller/id/page:2,则分页链接会自动转到http://www.example.com/dynamic-route/controller/id/page:3
我将所有分页代码放入一个元素中,并且我想将该元素包含在需要分页的视图文件中。
现在,如果我正在查看文章控制器、索引操作,分页链接的默认 URL 是 http://www.example.com/articles/page:2,但我需要它是 http://www.example.com/dynamic-route/articles/page:2
我尝试过使用
$this->Paginator->options = array(
'url' => 'http://www.example.com/dynamic-route/articles'
);
但链接的输出类似于http://www.example.com/articles/http://www.example.com/dynamic-route/articles/page:2
编辑: Jeztah,你提到放
'customlink' => '[a-z0-9]{1}([a-z0-9-]{2,}[a-z0-9]{1})?'
在我的路线上。好吧,我不能简单地这样做,因为路由会进行查询以检查 customlink 是否在数据库中,如果是则相应地路由。
我的路由器文件的一个例子是:
在获取 URL 的第一个参数 http://www.domain.com/CUSTOM-LINK 后,执行以下操作:
if($param1 != "users" && $param1){
$pagelink = str_replace('-', ' ', $param1);
$pagesModel = ClassRegistry::init('Page');
$matchedpage = $pagesModel->find('first', array(
'conditions' => array('Page.link LIKE' => "$pagelink"), 'recursive' => '-1'
));
if($matchedpage['Page']['id']){
Router::connect('/' . $param1 . '/:controller', array('action' => 'index', 'page_id' => $matchedpage['Page']['id']), array(
'pass' => array('page_id'),
'page_id' => '[0-9]+',
'persist' => array('page_id'),
));
Router::connect('/' . $param1 . '/:controller/:action/:id', array('page_id' => $matchedpage['Page']['id']), array(
'pass' => array('page_id', 'id'),
'page_id' => '[0-9]+',
'persist' => array('page_id'),
));
Router::connect('/' . $param1 . '/:controller/:id', array('action' => 'view', 'page_id' => $matchedpage['Page']['id']), array(
'pass' => array('page_id', 'id'),
'page_id' => '[0-9]+',
'id' => '[0-9]+',
'persist' => array('page_id'),
));
Router::connect('/' . $param1 . '/:controller/:action', array('page_id' => $matchedpage['Page']['id']), array(
'pass' => array('page_id'),
'page_id' => '[0-9]+',
'persist' => array('page_id'),
));
} // end if page matches
} // end if param1 is not users
如果我转到http://www.domain.com/custom-link/articles、http://www.domain.com/custom-link/articles/1、http://www.domain.com/custom-link/articles/edit/1 等,则会显示正确的页面。如果我尝试导航到自定义链接不存在的页面,请继续查看我的路由器文件,如果没有其他路由匹配,则抛出错误消息。一切都很好。
在我的 ArticlesController.php 中,重定向方法按预期工作。例如,我尝试转到http://www.domain.com/custom-link/articles/99,但 id 99 不存在,我使用
正确重定向回http://www.domain.com/custom-link/articles$this->redirect(array('action' => 'index', 'page_id' => $page_id), 空,真);
但是,在分页上,我将 url 选项设置为
array('controller' => 'articles', 'action' => 'index', 'page_id' => $page_id);
其中 $page_id 在 AppController 中设置为由路由器传递。虽然我不需要设置控制器和动作,因为将使用电流。同样,我的分页链接显示为 http://www.domain.com/articles/page_id:3/page:2 而不是我想要的 http://www.domain.com/custom-link/articles/page:2
编辑:杰兹塔
我刚刚将整个路由文件更改为具有自定义链接参数的文件(我重命名为“链接”),然后创建了一个组件以在应用程序控制器中使用以从链接中获取页面 ID。
示例路线
Router::connect('/:link/:controller/:action/:id', array(), array(
'pass' => array('link', 'id'),
'link' => '[a-z0-9]{1}([a-z0-9\-]{2,}[a-z0-9]{1})?',
'persist' => array('link'),
));
Router::connect('/:link/:controller/:id', array('action' => 'view'), array(
'pass' => array('link', 'id'),
'link' => '[a-z0-9]{1}([a-z0-9\-]{2,}[a-z0-9]{1})?',
'id' => '[0-9]+',
'persist' => array('link'),
));
但是,如果将 url 数组分页为 array('link' => 'test-example'),则 url 会输出为 http://www.domain.com/articles/link:test-example/page:2。我的代码与您的代码完全相同,减去将“自定义链接”重命名为“链接”。此外,现在我的路线无法区分我是否尝试访问http://www.domain.com/custom-link,这将是 'controller' => 'pages'、'action' => 'view' (他的页面基本上会使用 News 模型和显示该页面的最新消息),如果我尝试访问http://www.domain.com/articles,这将是“控制器”=>“文章”,“操作”=>“索引”,它将显示所有页面的最新文章。请注意,文章和新闻是不同的模型。
Router::connect('/:link', array('controller' => 'pages', 'action' => 'view'), array(
'pass' => array('link'),
'link' => '[a-z0-9]{1}([a-z0-9\-]{2,}[a-z0-9]{1})?',
'persist' => array('link'),
));
和
一样Router::connect('/:controller', array('action' => 'index'));
因为在路由中不再检查“链接”是否属于特定页面。
编辑:好的,我正在取得进展。我发现下一个和上一个分页链接不太适合 paginator->options。我删除了 paginator->options 并将下一个按钮的 url 数组留空。链接输出为http://www.domain.com/articles/custom-link/articles/page:2。进步!但是有什么办法可以赶上第一个“文章/”吗?
我的路线是
Router::connect('/:link/:controller/*', array(), array(
'link' => '[a-z0-9]{1}([a-z0-9\-]{2,}[a-z0-9]{1})?',
));
【问题讨论】:
-
您应该不动态创建路由,而是将“自定义链接”作为参数传递给控制器。这样,控制器将检查是否可以找到自定义链接,否则将显示常规 404(如果找不到页面,则应该如此)。您可能会考虑将自定义网址设为 必需,如果用户没有提供,请生成一个,但它应该是唯一的。如果为每个请求动态生成路由,CakePHP 将不得不为每个请求重新构建路由,这对性能不利
标签: php cakephp pagination routes paginator