的Symfony:关于路由和敲击
为了不显示我的社交网络中的URL成员的ID的问题,我创造了这个路线:的Symfony:关于路由和敲击
perfil_miembro:
url: /miembros/:nombre_apellidos
class: sfDoctrineRoute
options: { model: Usuario, type: object}
param: { module: miembros, action: show}
并补充在表演动作这一行:
$this->usuario = $this->getRoute()->getObject();
它的工作原理确定:当我点击他们的名字对应的轮廓显示和URL是这样的类型:
frontend_dev.p HP/miembros /玛丽亚+德+米格尔+阿尔瓦拉多
现在我想一决高下的URL的名字,所以我已经改变了路线是这样的:
perfil_miembro:
url: /miembros/:nombre_apellidos_slug
class: sfDoctrineRoute
options: { model: Usuario, type: object}
param: { module: miembros, action: show}
而且我已经创建了这些方法:现在
public function getNombreApellidosSlug()
{
return Tirengarfio::slugify($this->getNombreApellidos());
}
class Tirengarfio
{
static public function slugify($text)
{
// replace all non letters or digits by -
$text = preg_replace('/\W+/', '-', $text);
// trim and lowercase
$text = strtolower(trim($text, '-'));
return $text;
}
}
当我点击一个成员的名称,该URL显示:
frontend_dev.php/miembros/maria-de-miguel-alvarado
但它总是显示我在夹具文件中的第一个成员的配置文件。
我该如何让它工作?
Ubuntu 8.04 - Symfony 1.3。
slug字段需要是真实的列,而不是您创建的虚拟列。
当访问url时,doctrine正在寻找与url中找到的字段匹配的单个对象 - 在你的情况下,这意味着没有字段,即 为什么你看到表中的第一条记录。查询记录器 应显示类似select * from tablename limit 1;
。
关于您的网址的说明:您确定不会有多个同名的 人吗?如果发生这样的碰撞,没有人能够看到第二,第三等人的页面。我会将这个ID包含在url中,形式为/miembros/:id/:slug
,这样它可以保持人类可读性,并且肯定不会相互冲突。
UPDATE
在第一个评论,@Raise建议使用ID而不是ID本身的盐渍哈希。这比我最初的想法包括ID更好。
sfDoctrineGuardPlugin为每个用户生成一个新盐,并将其存储,并用于设置/验证密码。您需要在用户表中为该散列添加一个新字段(该盐不需要存储,ID不会更改),并且您的url将看起来像/miembros/:hash/:slug
。
你可以使用这些选项的路由:options: { model: Usuario, type: object, method: getObjectBySlug }
,但你需要 a getObjectBySlug()
方法,检索你的对象给一个slu。。现在你有getNombreApellidosSlug()
,恰恰相反。问题是,通常没有办法知道slu“”maria-martinez“是否对应于用户”Maria Martinez“,”MaríaMartínez“,”MaRiA MaRtInEz“或”MaríaMartíñez“,这是一个问题。你可以通过一个“slug”列来解决它。
我的建议是使用Sluggable behaviour of Doctrine,这需要照顾slug列。
我在this pet project上用它来做到这一点。它使用起来很漂亮straightforwards:
首先,您激活它在the schema:
actAs:
Timestampable: ~
Sluggable:
fields: [name]
indexName: name_slug
canUpdate: true
unique: true
,将创建和十个分量名为“塞”一栏。
然后,在the routing中使用它。在我的情况是:
list_permalink:
url: /:slug
class: sfDoctrineRoute
options: { model: SkinnyList, type: object, method: getObjectBySlug }
param: { module: list, action: show }
requirements: { sf_method: get }
你需要在lib/model/doctrine/yourmodelTable.class.php的方法getObjectBySlug:
public function getObjectBySlug($options = array())
{
if (!isset($options['slug']))
{
throw new InvalidArgumentException('The slug is required in the options');
}
$q = $this->createQuery('td')->where('td.slug = ?', $options['slug']) ;
return $q->fetchOne();
}
在操作,您可以通过检索对象:
$this->list = $this->getRoute()->getObject();
+1建议'uniquify'的网址,以避免冲突,虽然我认为一些散列的id和盐会更好 - 避免暴露id到网站。 Doctrine是否真的构建了这样的查询,并返回数据库中的第一行?如果这是真的,那很令人担忧。 – Raise 2010-07-13 22:43:01
@提高散列是一个好主意。关于查询建立,我是推动用户,但根据症状,这是我能想象的唯一方式。我同意计数可能是为了查看记录与查询的匹配程度,但这不是必须的。 – Maerlyn 2010-07-14 08:09:53
谢谢Maerlyn,你写过“我会在URL中包含ID”,但这不是一个好习惯,你可以在这里看到(搜索永久链接)http://www.symfony-project.org/gentle-introduction/1_4/en/09-Links-and-the-Routing-System – ziiweb 2010-07-14 09:33:54