我的项目中有几个与每个对象类型相关的url。实施例
对于产品:
/product/product-1
/product/product-2
但现在我为一般信息管理创建了一个控制器。防爆。使用条款,关于我们..等等。
我想要只包含页面slug的网址。
/terms-use
/about-us
不
/page/terms-use
/page/about-us
如何在routing.yml中定义它?
答案 0 :(得分:1)
Venu是对的,Custom symfony routing based on doctrine提供了一种方法来做到这一点,唯一的复杂因素是如果你的slug参数是通过添加父页面的slug来构建的,那么孙子页面就像grandparent-slug/parent-slug/child-slug
一样有一个slug在哪种情况下会抛出异常。
我们使用路由来匹配slug,就像我给出的示例一样,它需要注释中的一些正则表达式:
/**
* @Route("{slug}", name="page_index", defaults={"slug" = false}, requirements={"slug" = "[0-9a-zA-Z\/\-]*"})
* @Template()
*/
public function indexAction($slug)
{
if ($slug !== false) {
$page = $this->findPage($slug);
上述要求注释意味着slug可以是带正斜杠和连字符的字母数字。然后,您需要实现一个方法findPage($slug)
,它会在正斜杠上展开slug并找到正确的子页面。
因为路由与许多其他路由匹配,所以最后将此控制器包含在routing.yml文件中,并将此操作包含在控制器中的最后一个公共操作中,以便首先匹配所有其他路由。
这是我们编写的findPage方法,用于从上面的slug中找到一个页面:
protected function findPage($slug_string, $first_page = false)
{
$slug_array = explode("/", $slug_string);
$slug = array_shift($slug_array);
$page = $this->em->getRepository("PagesBundle:Page")->getPageBySlug($slug, $this->site_id);
if (!$page) {
return false;
}
// if only the first matched page is required return it
if ($first_page) {
return $page;
}
// Otherwise loop through the slug array and match recursive
//children until slug array is empty or no match found
while (!empty($slug_array)) {
if ($page->getChildren()) {
$slug = array_shift($slug_array);
foreach ($page->getChildren() as $child_page) {
if ($child_page->getSlug() == $slug) {
$page = $child_page;
break;
}
}
} else {
return false;
}
}
return $page;
}