Symfony2:如何仅使用slug设置url

时间:2013-01-18 00:29:06

标签: symfony routing

  

可能重复:
  Custom symfony routing based on doctrine

我的项目中有几个与每个对象类型相关的url。实施例

对于产品:

/product/product-1
/product/product-2

但现在我为一般信息管理创建了一个控制器。防爆。使用条款,关于我们..等等。

我想要只包含页面slug的网址。

/terms-use
/about-us

/page/terms-use
/page/about-us

如何在routing.yml中定义它?

1 个答案:

答案 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;
}