Zend Framework - cms 页面路由
我有一个 CMS,管理员在其中构建自己的递归页面结构。每个页面都有自己的“url-key”。接下来,将 url-key 与页面结构结合使用来构建 URL 结构,以便您获得以下结构:
{rootpage url-key}/{subpage url-key}
可选地,多语言支持已开启,您还可以获得语言前缀:
{language code}/{rootpage url-key}/{subpage url-key}
我几乎通过为每个页面提供它自己的静态路由,然后将它们链接在一起。
/**
* Initializes the sites navigation.
*
* @param array $pages An array with the cms pages to initialize
*/
protected function _initNavigation(array $pages = null)
{
$root = true;
if ($pages === null) {
$pages = Sjr_App::get()->getModel('page')->getTree();
$root = true;
}
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
foreach ($pages as $page) {
$router->addRoute($page->getRouteName(), $page->getRoute());
if ($page->children) {
$this->_initNavigation($page->children);
}
}
}
$page->getRoute():
/**
* Gets the routing for the page.
*
* @return Zend_Controller_Router_Route_Abstract
*/
public function getRoute()
{
if ($this->_route === null) {
$this->_route = new Zend_Controller_Router_Route_Static($this->url_key,
$this->getNavigationData()
);
if ($this->parent) {
$parentRoute = $this->parent->getRoute();
$this->_route = $parentRoute->chain($this->_route);
}
}
return $this->_route;
}
接下来,如果支持多语言,我会在所有路由前面加上语言路由:
foreach ($front->getRouter()->getRoutes() as $routeName => $route) {
if ($routeName != 'lang') {
$front->getRouter()->addRoute($routeName, $this->_languageRoute->chain($route));
}
}
所有路由都正确组装。但是,一旦页面具有和/或是子页面,路由就不会匹配。
但除了它还没有工作之外,我还想知道这是否是最好的方法。页面结构可能会变得相当大,这意味着它还会创建大量路由对象。我不确定这对性能有什么影响。
或者,我正在考虑编写一个自定义路由器/路由来处理 1 个路由中的所有 cms 路由。这也将使组装 cms-url 变得更容易。
我希望有人可以就这个问题给我一些建议。
I have a CMS where the admin builds its own recursive page structure. Every page has its own "url-key". Next the url-key is used in combination with the page structure to build the URL structure so you get the following structure:
{rootpage url-key}/{subpage url-key}
Optionally, multilanguage supporst is on and you also get a language prefix:
{language code}/{rootpage url-key}/{subpage url-key}
I almost got the above working by providing each page with its own static route and then chaining them together.
/**
* Initializes the sites navigation.
*
* @param array $pages An array with the cms pages to initialize
*/
protected function _initNavigation(array $pages = null)
{
$root = true;
if ($pages === null) {
$pages = Sjr_App::get()->getModel('page')->getTree();
$root = true;
}
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
foreach ($pages as $page) {
$router->addRoute($page->getRouteName(), $page->getRoute());
if ($page->children) {
$this->_initNavigation($page->children);
}
}
}
$page->getRoute():
/**
* Gets the routing for the page.
*
* @return Zend_Controller_Router_Route_Abstract
*/
public function getRoute()
{
if ($this->_route === null) {
$this->_route = new Zend_Controller_Router_Route_Static($this->url_key,
$this->getNavigationData()
);
if ($this->parent) {
$parentRoute = $this->parent->getRoute();
$this->_route = $parentRoute->chain($this->_route);
}
}
return $this->_route;
}
Next, if multilanguage is supported, i prepend all the routes with the language route:
foreach ($front->getRouter()->getRoutes() as $routeName => $route) {
if ($routeName != 'lang') {
$front->getRouter()->addRoute($routeName, $this->_languageRoute->chain($route));
}
}
All the routes are assembled correctly. But once a page has and/or is a child the routes arent matched.
But aside from it not working yet, im also wondering if this is the best approach. The page structure could get pretty big, meaning it would also create alot of route objects. I'm not sure what effect this has on performance.
Alternatively i was thinking about writing a custom router/route to handle all the cms-routes in 1 route. This would also make it easier to assemble cms-urls.
I hope someone can give me some advice on this issue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为你的方法应该有效(原则上)。当我从事类似的工作时,令我困扰的一件事是,您不能将路由链用作“树”,在“树”中,您有一个顶级路由,其下有多个路由选项。
因此,如果您有:
这些需要是三个完全独立的路线。您不能通过添加 /foo 和 /bar 来重用 /something 的一个路由对象,并期望路由器能够确定使用哪一个。如果您的 $this->parent 方法正在重用页面,这可能就是您的问题所在。
但是,我认为您想知道这是否是最好的方法是正确的。它应该适用于小型站点,但由于在循环中检查路由直到找到匹配项,如果站点有 10,000 个页面,那么这将是一个非常慢的路由过程,并且路由器将执行大量重复任务。
另一种方法是使用自定义路由类,它能够根据数据库中的键检查相关路由部分。这样,您应该能够只用一条路线完成所有工作,这会快得多。
我不久前发表了一篇博客文章有一些代码示例说明了如何以这种方式处理虚荣 URL,因此尽管这是一个不同的问题,但解决方案是相同的(自定义路由类),因此它可能会为您指明正确的方向。
I think your approach should work (in principle). One thing that bit me when I was working on something similar was that you can't use route chains as a 'tree', where you have one top level route with multiple route options under it.
So if you have:
these need to be three completely separate routes. You can't have one route object for /something which you reuse by adding /foo and /bar to, expecting the router to be able to work out which one to use. If your $this->parent method is reusing pages this might be where your problem is.
However, I think you are right to wonder whether this is the best approach. It should work for small sites, but as routes are checked in a loop until a match is found, if a site had 10,000 pages then this would be a pretty slow routing process, and the router would be doing a lot of repetitive tasks.
An alternative would be to use a custom route class which is able to check the relevant route part against the keys in the database. This way you should be able to do it all with just one route, which would be considerably faster.
I put up a blog post a while back with some code examples of how do vanity URLs in this way, so although this is a different problem the solution is the same (custom route class), so it might point you in the right direction.