2010-07-13 47 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();