2010-07-13 46 views
1

为了不显示我的社交网络中的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。

回答

1

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

+0

+1建议'uniquify'的网址,以避免冲突,虽然我认为一些散列的id和盐会更好 - 避免暴露id到网站。 Doctrine是否真的构建了这样的查询,并返回数据库中的第一行?如果这是真的,那很令人担忧。 – Raise 2010-07-13 22:43:01

+0

@提高散列是一个好主意。关于查询建立,我是推动用户,但根据症状,这是我能想象的唯一方式。我同意计数可能是为了查看记录与查询的匹配程度,但这不是必须的。 – Maerlyn 2010-07-14 08:09:53

+0

谢谢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

1

你可以使用这些选项的路由: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();