2014-03-18 3 views
0

Я пытаюсь разобраться с псевдонимами (дружественными URL-адресами) и, вероятно, я не делаю это правильно. Что я хочу сделать, так это преобразовать URL-адреса, например «/ blog/my-post-about-something» в «/ posts/23».Невозможно перезаписать pathInfo в запросе Symfony 2

Я написал слушателя для kernel.request события, что делает некоторые операции и модифицирует исходный запрос

class RequestListener 
{ 

    public function onKernelRequest(KernelEvent $event) 
    { 
     $request = $event->getRequest(); 
     $converted_path = $this->getPathIfAny($request); 
     if ($converted_path) { 
      $request->server->set('REQUEST_URI', $converted_path); 
     } 
    } 

    public function getPathIfAny(Request $request) 
    { 
     return $somePathOrNull; 
    } 
} 

Вся логика работает должным образом и обновляет первоначальный запрос. Проблема в том, что даже если я изменяю «REQUEST_URI», свойство $ pathInfo остается неизменным и указывает на предыдущий путь, поэтому я продолжаю получать 404 ошибки.

Есть ли способ полностью переопределить uri, или я должен попытаться решить проблему по-другому?

Вот определение приемника

my_cmf.request_listener: 
    class: My\CMFBundle\Event\RequestListener 
    tags: 
     - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest , priority: -10} 

Связанные ссылки к этому вопросу: https://github.com/symfony/symfony/issues/10478

ответ

4

У меня есть аналогичная проблема с моим проектом.Я был в состоянии обновить информацию пути, но по-прежнему изо всех сил, чтобы получить это прошло последующие события

Попробуйте это:

$event->getRequest()->server->set('REQUEST_URI', '/en/guestbook'); 
$event->getRequest()->initialize($event->getRequest()->query->all(), $event->getRequest()->request->all(), $event->getRequest()->attributes->all(), $event->getRequest()->cookies->all(), $event->getRequest()->files->all(), $event->getRequest()->server->all(), $event->getRequest()->getContent()); 

var_dump($event->getRequest()->getPathInfo()); 

Метод инициализации сбрасывает весь класс.

+0

Он работает и решает проблему более чистым способом, спасибо вам большое. – carles

0

На самом деле, это не поведение предполагается использовать.

Реальный вопрос: «Я хочу преобразовать/пост/мой-супер-пост в/пост/1234», но «Я хочу получить хорошую должность при использовании своего псевдонима».

Во-первых, убедитесь, что ваш объект Post имеет атрибут UNIQUE slug (который будет содержать здесь «my-super-post»). Они могут быть сгенерированы пакетом расширения доктрины STOF.

Затем на вашем routing.yml, использовать что-то вроде:

show_post: 
    path: /post/{slug} 
    defaults: { _controller: AcmeFooBundle:Bar:showPost } 

и в контроллере:

public function showPostAction(Post $post) { 
... 
} 

автоматически, содержащие $post вы ищете.

Вы можете найти подробную информацию о слизнях здесь: http://symfony.com/doc/current/cookbook/doctrine/common_extensions.html и ParamConverters здесь: http://symfony.com/doc/2.0/bundles/SensioFrameworkExtraBundle/annotations/converters.html

+0

Спасибо @ Kanalkite, но это не намеренный дизайн библиотеки. Я бы предпочел решение, которое решает любой «алиасируемый» объект без необходимости писать пути и методы контроллера и избегать зависимости от Doctrine и его расширений. – carles

1

расследующих немного больше, я нашел an issue on the Symfony2 github repository, что говорит об этой проблеме. Похоже, что это замечательный недостаток дизайна в классе Request, который будет исправлен в Symfony 3. *. К настоящему времени я нашел временное решение.

Решение проблем кеширования класса Request возможно путем его расширения и добавления метода, который очищает кэшированные данные.

use Symfony\Component\HttpFoundation\Request as BaseRequest; 

class Request extends BaseRequest 
{ 
    public function clearCache() 
    { 
     $this->requestUri = null; 
     $this->pathInfo = null; 
     $this->requestUri = null; 
     $this->baseUrl = null; 
     $this->basePath = null; 
    } 
} 

Тогда можно обойти проблему от слушателя, вызвав новый метод.

public function onKernelRequest(KernelEvent $event) 
{ 
    $request = $event->getRequest(); 
    $converted_path = $this->getPathIfAny($request); 
    if ($converted_path) { 
     $request->clearCache(); 
     $request->server->set('REQUEST_URI', $converted_path); 
    } 
} 

Очистка кэша, вероятно, имеет небольшой эффект в производительности приложения, но я уверен, что он не будет заметен, так как кэш будет строятся только два раза.

1

Вы можете сделать запрос для ядра, но с другой информацией о пути.

$url = 'Your url here...'; 
    $subRequest = $request->duplicate(
     null, // query 
     null, // request 
     null, // attributes 
     null, // cookies 
     null, // files 
     array_merge($request->server->all(), [ 
      'REQUEST_URI' => $url, 
     ]) 
    ); 

    return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST); 

 Смежные вопросы

  • Нет связанных вопросов^_^