Symfony: вопрос о маршрутизации и слизняках - PullRequest
1 голос
/ 13 июля 2010

Чтобы не отображать идентификаторы участников моей социальной сети в URL, я создал этот маршрут:

perfil_miembro:
  url: /miembros/:nombre_apellidos
  class: sfDoctrineRoute
  options: { model: Usuario, type: object}
  param: { module: miembros, action: show}

И добавил эту строку в действие 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.

Ответы [ 2 ]

1 голос
/ 17 июля 2010

Вы можете использовать эти параметры маршрутизации: options: { model: Usuario, type: object, method: getObjectBySlug }, но вам нужен метод getObjectBySlug(), который извлекает ваш объект с заданным слагом. Теперь у вас есть getNombreApellidosSlug(), что делает наоборот. Проблема в том, что обычно нет способа узнать, соответствует ли слаг «maria-martinez» пользователю «Мария Мартинес», «Мария Мартинес», «Мария Маринез» или «Мария Мартинес», так что это проблема. Вы можете решить эту проблему с помощью столбца «slug».

Мой совет - использовать Sluggable поведение 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 голос
/ 13 июля 2010

Поле слага должно быть реальным столбцом, а не виртуальным, который вы создали.
При обращении к URL-адресу, доктрина ищет один объект, соответствующий полям, найденным в URL-адресе - в вашем случае этоозначает отсутствие полей, поэтому вы видите самую первую запись в вашей таблице.Регистратор запросов должен показывать что-то вроде select * from tablename limit 1;.

Примечание относительно вашего URL: вы уверены, что не будет нескольких людей с одним именем?Если такое столкновение происходит, никто не сможет увидеть страницу 2-го, 3-го и т. Д. Человека.Я бы включил идентификатор в URL в виде /miembros/:id/:slug, чтобы он оставался читаемым человеком и, конечно, не столкнулся.

ОБНОВЛЕНИЕ
В первомкомментарий, @Raise предлагает использовать соленый хеш идентификатора вместо самого идентификатора.Это лучше, чем моя первоначальная идея включения идентификатора.
sfDoctrineGuardPlugin генерирует новую соль для каждого пользователя, сохраняет ее и используется для установки / проверки пароля.Вам понадобятся новые поля в вашей таблице пользователей для хэша (соль не нужно хранить, идентификатор не изменится), и ваш URL будет выглядеть как /miembros/:hash/:slug.

...