无法覆盖Symfony 2请求中的pathInfo

时间:2014-03-18 11:02:56

标签: symfony routing aliasing

我试图处理别名(friendly-urls),可能我没做对。我想做的是转换网址,例如' / blog / my-post-about-something'进入' / posts / 23'。

我为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 个答案:

答案 0 :(得分: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());

initialize方法重置整个类。

答案 1 :(得分: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;
    }
}

然后可以通过调用new方法从侦听器中绕过问题。

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);
    }
}

清除缓存可能会对应用程序的性能产生很小的影响,但我确信它不会引起注意,因为缓存只会被构建两次。

答案 2 :(得分: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);

答案 3 :(得分:0)

事实上,这不是应该使用的行为。

真正的问题不是"我想将/ post / my-super-post转换为/ post / 1234",但是"我想在使用别名时获得好帖子&# 34。

首先,确保您的Post实体具有UNIQUE slug属性(其中包含" my-super-post"此处)。这些可以由STOF Doctrine Extension Bundle生成。

然后,在您的routing.yml上,使用类似:

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

并在您的控制器中:

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

将自动包含您要查找的$post

您可以在此处找到有关slu的更多信息:http://symfony.com/doc/current/cookbook/doctrine/common_extensions.html 和ParamConverters:http://symfony.com/doc/2.0/bundles/SensioFrameworkExtraBundle/annotations/converters.html