Для не показа идентификатора членов моей социальной сети в URL я создал этот маршрут:
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.php/miembros/Maria+de+Miguel+Alvarado
Теперь я хотел бы отложить имена в 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, доктрина ищет один объект.
соответствующий полям, найденным в url - в вашем случае это означает отсутствие полей, поэтому
поэтому вы видите самую первую запись в вашей таблице. Регистратор запросов
должен показать что-то вроде select * from tablename limit 1;
.
Замечание относительно вашего url: вы уверены, что не будет нескольких
людей с одинаковым именем? Если такая коллизия произойдет, никто не сможет
никто не сможет увидеть страницу 2-го, 3-го и т.д. человека. Я бы включил ID в url, в виде /miembros/:id/:slug
, так он останется человекочитаемым и точно не столкнется.
UPDATE
В первом комментарии @Raise предложил использовать соленый хэш ID вместо самого ID. Это лучше, чем моя первоначальная идея включить ID.
Плагин sfDoctrineGuardPlugin генерирует новую соль для каждого пользователя, сохраняет ее, и она используется для установки/проверки пароля. Вам понадобится новое поле в таблице users для хэша (соль не нужно хранить, ID не изменится), и ваш url будет выглядеть как /miembros/:hash/:slug
.
Вы можете использовать следующие параметры маршрутизации: options: {model: Usuario, type: object, method: getObjectBySlug}
, но вам понадобится a getObjectBySlug ()
метод, который извлекает ваш объект по слагу. Теперь у вас есть getNombreApellidosSlug ()
, который делает прямо противоположное. Проблема в том, что обычно нет способа узнать, соответствует ли ярлык «maria-martinez» пользователю «Мария Мартинес», «Мария Мартинес», «MaRiA MaRtInEz» или «Мария Мартинес», так что это проблема. Вы можете решить эту проблему с помощью столбца «слизняк».
Мой совет - использовать Замедленное поведение Doctrine , которое заботится о столбце заголовка.
Я использую его в этом домашнем проекте именно для этого. Использовать его довольно просто:
Сначала вы активируете его в схеме :
actAs:
Timestampable: ~
Sluggable:
fields: [name]
indexName: name_slug
canUpdate: true
unique: true
И он создает и поддерживает столбец с именем «slug».
Затем используйте его в маршрутизации . В моем случае это:
list_permalink:
url: /:slug
class: sfDoctrineRoute
options: { model: SkinnyList, type: object, method: getObjectBySlug }
param: { module: list, action: show }
requirements: { sf_method: get }
Вам понадобится метод getObjectBySlug в lib / model / doctrine / yourmodelTable.class.php :
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();