Symfony: вопрос о маршрутизации и отсрочке

Для не показа идентификатора членов моей социальной сети в 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.

1
задан Peter Mortensen 18 August 2010 в 20:01
поделиться

2 ответа

Поле 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.

1
ответ дан 2 September 2019 в 23:05
поделиться

Вы можете использовать следующие параметры маршрутизации: 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();
1
ответ дан 2 September 2019 в 23:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: