我正在尝试处理别名(友好的url),可能我做得不对。我想做的是将url转换为'/blog/my-post-about-something'到'/posts/23'。
我为内核编写了一个侦听器。进行一些操作并修改原始请求的请求事件
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: MyCMFBundleEventRequestListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest , priority: -10}
此问题的相关链接:https://github.com/symfony/symfony/issues/10478
我的项目也有类似的问题。我能够更新路径信息,但仍然难以将其传递给后续事件
试试这个:
$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方法重置整个类
你可以为内核发出子请求,但是用另一个路径info.
$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);
进一步调查后,我发现Symfony2 github存储库中存在一个问题。似乎这是Request类中一个值得注意的设计缺陷,将在Symfony 3.*中修复。到目前为止,我已经找到了一个临时的解决方案。
通过扩展Request类并添加一个清除缓存数据的方法来处理Request类的缓存问题。
use SymfonyComponentHttpFoundationRequest 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);
}
}
清除缓存可能会对应用程序的性能产生很小的影响,但我相信这不会很明显,因为缓存将只构建两次。
事实上,这不是应该使用的行为。
真正的问题不是"我想将/post/my-super-post转换为/post/1234",而是"我想在使用别名时获得好帖子"。
首先,确保你的Post实体有一个UNIQUE的属性(这里包含"my-super-post")。这些可以由STOF Doctrine扩展包生成。
然后,在你的路由。在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和参数转换器:http://symfony.com/doc/2.0/bundles/SensioFrameworkExtraBundle/annotations/converters.html