问题
I'm trying to deal with aliases (friendly-urls) and probably I'm not doing it right. What I want to do is to transform urls like '/blog/my-post-about-something' into '/posts/23'.
I have written a listener for the kernel.request event that makes some operations and modifies the original 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;
}
}
All the logic works properly and updates the original request. The problem is, even if I change the 'REQUEST_URI', the property $pathInfo remains unaltered and pointing to the previous path, so I keep getting 404 errors.
Is there any way to override the uri completely, or should I try to solve the problem in a different manner?
Here is the listener definition
my_cmf.request_listener:
class: My\CMFBundle\Event\RequestListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest , priority: -10}
Related link to this issue: https://github.com/symfony/symfony/issues/10478
回答1:
I have a similar issue with my project. I was able to update the path info, but still struggling to get it passed to subsequent events
Try this:
$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());
The initialize method resets the whole class.
回答2:
Investigating a bit more, I've found an issue on the Symfony2 github repository that speaks about the problem. Seems that it is a noticed design flaw in the Request class that will be fixed in Symfony 3.*. By now, I've found a provisional solution.
Dealing with the caching issues of the Request class is possible by extending it and adding a method that cleans the cached data.
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;
}
}
Then it is possible to bypass the problem from the listener by calling the new method.
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);
}
}
Clearing the cache will probably have a small effect in the performance of the app, but I'm sure it won't be noticeable, since the cache will be being built only twice.
回答3:
You can make sub-request for kernel but with another path 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);
回答4:
In fact, this is not the behaviour supposed to be used.
The real question is not "I want to transform /post/my-super-post into /post/1234", but "I want to get the good post when using its alias".
First, make sure your Post entity have a UNIQUE slug attribute (which would contains the "my-super-post" here). Those can be generated by the STOF Doctrine Extension Bundle.
Then, on your routing.yml, use something like :
show_post:
path: /post/{slug}
defaults: { _controller: AcmeFooBundle:Bar:showPost }
and in your controller :
public function showPostAction(Post $post) {
...
}
will automatically be containing the $post you are looking for.
You can find more informations about slugs here : http://symfony.com/doc/current/cookbook/doctrine/common_extensions.html and ParamConverters here : http://symfony.com/doc/2.0/bundles/SensioFrameworkExtraBundle/annotations/converters.html
来源:https://stackoverflow.com/questions/22477408/unable-to-overwrite-pathinfo-in-a-symfony-2-request