CakePHP - 如何使用 slug 进行反向路由?

Posted

技术标签:

【中文标题】CakePHP - 如何使用 slug 进行反向路由?【英文标题】:CakePHP - How to do reverse routing with slug? 【发布时间】:2011-07-03 19:50:59 【问题描述】:

我正在使用 Cakephp 1.3。我有一个产品模型。在 DB 表中,有 idslug 字段。

如果我有一个产品是 id:37slug:My-Product-Title,我希望产品的 URL 是:

products/37/My-Product-Title

代替标准:

产品/视图/37

我创建了一条如下所示的路线:

Router::connect(
    '/products/:id/:slug',
    array('controller' => 'products', 'action' => 'view'),
    array('pass' => array('id'), 'id' => '[0-9]+')
);

现在我可以去http://server/products/37/My-Product-Title,它会把我带到正确的地方。

但是如何获得反向路由以在$htmlHelper->link 中自动构建正确的 URL?

当我使用时:

echo $html->link(
    'Product 37', 
    array('controller'=>'products', 'action' => 'view', 37)
);

它仍然输出标准的products/view/37 url。

【问题讨论】:

我知道这不是直接相关的,但如果你还没有看过的话,我建议你看看 pseudocoder 的 cakephp 书 (pseudocoder.com/archives/…) 中关于 slug 的部分。 【参考方案1】:

我不相信可以自动魔术般地完成。助手只是一个从给定参数构建链接的“助手”。

所以最简单的方法是在链接中添加另一个参数,如下所示:

echo $html->link(
    'Product 37', 
    array('controller'=>'products', 'action' => 'view', 37, $slug)
);

$slug 是来自 slug 字段的数据。

也许你的想法可以做到,但你需要非常糟糕地打破 MVC 模式:)

编辑:

再次阅读您的问题,我很好理解。看看应该怎么做:

在你的 router.php 中添加以下规则:

Router::connect(
    '/product/*',
    array('controller' => 'products', 'action' => 'view')
);

请注意,它是 /product/* 而不是 /products/*

你的链接应该是这样的:

echo $html->link(
    'Product 37', 
    array('controller'=>'products', 'action' => 'view', 37, 'my-product-title')
);

链接看起来像:

http://yourdomain.com/product/37/my-product-title

对我来说,做你的建议是不好的做法。另外,从 SEO 的角度来看,我认为始终重定向用户并不是一件好事。

【讨论】:

不幸的是,这会将 URL 构建为 /products/view/37/my-product-title 我不想要 view 在那里。如果我通过array('controller'=>'products', 'action' => 37, 'my-product-title') 确实有效,但感觉不对。【参考方案2】:

对于路由:

Router::connect(
    '/products/:id/:slug',
    array('controller' => 'products', 'action' => 'view'),
    array('pass' => array('id'), 'id' => '[0-9]+')
);

您的链接应如下所示:

echo $html->link(
    'Product 37', 
    array('controller'=>'products', 'action' => 'view', 'id' => 37, 'slug' => 'my-product-title')
);

您必须为路由中的每个 :param 添加额外的(键 => 值)到您的数组中。那么魔法就会起作用

【讨论】:

实际上我不确定这是否是给定问题的答案,但它至少正是我想要的 =) 谢谢!【参考方案3】:

你应该看看下面关于自定义路由类的帖子。

slug 数据根本不需要与数据库相关 - 该字段是用于简化逻辑和查找的假字段。此解决方案允许您反转路由 slug,而无需模型表中的 slug 字段。

http://42pixels.com/blog/slugs-ugly-bugs-pretty-urls

【讨论】:

同意您的观点,如果网址采用上述格式,则 slug 仅用于 SEO。 如果你想要不同的格式,它足够灵活,可以用作基础。问题是,slug 始终是一个计算域,因此不需要存储,因为它可以动态计算。【参考方案4】:

我不确定这有多糟糕,但 ProductsController 中有以下代码:

function view($id)

    if( isset($_SERVER) && stristr($_SERVER["REQUEST_URI"],'view/') )
    
        $this->Product->id = $id;
        $slug = $this->Product->field('slug');
        $this->redirect($id.'/'.$slug);
    
    $data = $this->Product->find('first', array('conditions' => array('Product.id' => $id)));
    $this->set("data", $data);

如果页面是通过/view/id 访问的,它会自动使用/id/slug 将它们重定向到当前页面

现在我可以使用默认链接方案了:

echo $html->link(
    'Product 37', 
    array('controller'=>'products', 'action' => 'view', 37)
);

他们将被重定向到正确的 URL。

唯一的问题是我不确定每次用户访问产品页面时都发生重定向有多糟糕?

【讨论】:

以上是关于CakePHP - 如何使用 slug 进行反向路由?的主要内容,如果未能解决你的问题,请参考以下文章

CakePHP:如何获取与 slug 匹配的行的 ID?

CakePHP 反向路由:Html 链接未显示正确的链接

更改加密 cakephp 脚本的 url slug

在 CakePHP 中保留父 slug

使用 cakePHP 的多种 slug 类型

CakePHP 通过 slug 而不是 ID 过滤列表