【问题标题】:Add a query param to all urls generated from routes automatically将查询参数添加到自动从路由生成的所有 url
【发布时间】:2014-03-19 20:21:13
【问题描述】:

我想将给定请求 url 的查询参数自动复制到我的路由生成的所有 url。

假设有人请求example.com/en?preview=true。因此,我希望在此页面上生成的所有 url 也自动附加 preview=true 查询参数,即不更新我的所有路由定义。

我尝试将预览参数添加为 onKernelRequest 侦听器中所有现有路由的默认值,但没有走得太远。

提前致谢

【问题讨论】:

  • 会话中的 storeage preview 值有什么问题?
  • 没什么,但有什么用?我只是不想触及现有代码中的每个树枝path 和控制器generateUrl

标签: symfony symfony-2.4


【解决方案1】:

我自己通过扩展默认框架路由器解决了这个问题。

# src/Your/Bundle/Resources/config/service.yml
parameters:
    router.class: Your\Bundle\Routing\PreviewRouter


<?php    
// src/Your/Bundle/Routing/PreviewRouter.php

namespace Your\Bundle\Routing;

use Symfony\Bundle\FrameworkBundle\Routing\Router as BaseRouter;

/**
 * extends the base router's generate function to always append
 * the preview query param on all generated urls
 */
class PreviewRouter extends BaseRouter
{

    public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
    {
        // parent router generates url
        $url = parent::generate($name, $parameters, $referenceType);

        // check for existing preview query string
        parse_str($this->getContext()->getQueryString(), $contextQueryParams);
        if(isset($contextQueryParams['preview']) && filter_var($contextQueryParams['preview'], FILTER_VALIDATE_BOOLEAN))
        {
            // put possible query string params into $queryParams array
            $urlParts = parse_url($url);
            parse_str(isset($urlParts['query']) ? $urlParts['query'] : '', $urlQueryParams);

            // strip everything after '?' from generated url
            $url = preg_replace('/\?.*$/', '', $url);

            // append merged query string to generated url
            $url .= '?'.http_build_query(array_merge(
                array('preview' => $contextQueryParams['preview']),
                $urlQueryParams
            ));
        }

        // remove preview param if set to false deliberately
        $url = preg_replace('/(\?|&)preview=(false|0|off)/', '', $url);

        return $url;
    }

}

【讨论】:

  • 这正是我所需要的。非常感谢。
【解决方案2】:

我有一个可能的实现,但是有一些警告。如果您生成的 url 上已经有查询字符串,这将不起作用。

您将需要创建一个新的 Twig 过滤器扩展。让我们从创建扩展类开始。您可能希望从 acme 演示中移动和更改它。

//src/Acme/DemoBundle/Twig/AcmeExtension.php
<?php
namespace Acme\DemoBundle\Twig;

class AcmeExtension extends \Twig_Extension
{
    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter('queryString', array($this, 'queryStringFilter')),
        );
    }

    public function queryStringFilter($array)
    {
        return http_build_query($array);
    }

    public function getName()
    {
        return 'acme_extension';
    }
}

然后您需要将此新扩展注册为服务:

//src/Acme/DemoBundle/Resources/config/services.yml
parameters:
    acme_demo.acme_extension.class: Acme\DemoBundle\Twig\AcmeExtension

services:
    acme_demo.acme_extension:
        class: %acme_demo.acme_extension.class%
        tags:
            - { name: twig.extension }    

然后你需要在你的主配置中包含这个新服务:

//app/config/config.yml
imports:
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: "@AcmeDemoBundle/Resources/config/services.yml" }    

然后,当您在树枝文件中生成路线时:

<a href="{{path('some_route_id')}}?{{app.request.query.all|queryString}}">This will have your query string appended.</a>

【讨论】:

  • 谢谢乔瑟。树枝扩展当然不是一个坏主意,但这就是我想要避免的,触摸我(不是那么小)应用程序中的每个模板和控制器。
【解决方案3】:

您可以将所有现有查询作为第二个参数添加到路径调用中:

<a href="{{ path('my_route', app.request.query.all)}}">My Link</a>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-26
    • 2019-05-30
    • 1970-01-01
    • 2021-09-29
    • 2016-01-01
    • 2018-06-16
    • 1970-01-01
    相关资源
    最近更新 更多