phpsymfonysymfony-2.4

Add a query param to all urls generated from routes automatically


I want to copy a query param of a given request url automatically to all urls generated by my routes.

Lets say someone requests example.com/en?preview=true. So I want all urls generated on this page to also have the preview=true query param appended automatically, i.e. without updating all my route definitions.

I tried adding the preview param as a default for all existing routes in a onKernelRequest listener but didn't get very far.

Thanks in advance


Solution

  • I've solved it myself by extending the default framework router.

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