0

我正在尝试处理别名(友好网址),可能我做得不对。我想要做的是将'/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

4 回答 4

5

我的项目也有类似的问题。我能够更新路径信息,但仍在努力将其传递给后续事件

尝试这个:

$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());

初始化方法重置整个类。

于 2014-03-18T16:01:54.653 回答
2

您可以使用其他路径信息对内核进行子请求。

    $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);
于 2015-03-06T16:18:39.370 回答
1

进一步调查后,我在 Symfony2 github 存储库上发现了一个问题,该问题说明了该问题。似乎这是 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);
    }
}

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

于 2014-03-18T14:26:59.243 回答
0

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

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

首先,确保您的 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您要查找的内容。

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

于 2014-03-18T13:03:56.960 回答