[Symfony] Get the routing information of the referer

Published on 2018-10-31 • Modified on 2018-11-03

Sometimes it is useful to get the referrer routing information when you have a page that have multiple access points. Knowing the context can therefore help you to customize the user output depending on the referrer route or its parameters. If you just want to get the referrer check out the snippet.


<?php

declare(strict_types=1);

namespace App\Controller\Snippet;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;

/**
 * I am using a PHP trait to isolate each snippet in a file.
 * This code should be called from a Symfony controller extending AbstractController (as of Symfony 4.2)
 * or Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Services are injected in the main controller constructor.
 *
 * @property RouterInterface $router
 */
trait Snippet7Trait
{
    public function snippet7(Request $request): void
    {
        $referer = $request->headers->get('referer'); // get the referer, it can be empty!
        if (!\is_string($referer) || $referer !== '') {
            echo 'Referer is invalid or empty.';

            return;
        }

        $refererPathInfo = Request::create($referer)->getPathInfo();

        // Remove the scriptname if using a dev controller like app_dev.php (Symfony 3.x only)
        $refererPathInfo = str_replace($request->getScriptName(), '', $refererPathInfo);

        // try to match the path with the application routing
        $routeInfos = $this->router->match($refererPathInfo);

        // get the Symfony route name
        $refererRoute = $routeInfos['_route'] ?? '';

        // No route found (external URL for example)
        if (!$refererRoute) {
            echo sprintf('No route found for the "%s" referer.', $referer);

            return;
        }

        // get the parameters, remove useless ones and add a parameter to test
        unset($routeInfos['_route'], $routeInfos['_controller']);
        $routeInfos['foo'] = 'bar';

        // Ok, now we can generate a new URL for this referer with new parameters
        try {
            $newUrl = $this->router->generate($refererRoute, $routeInfos); // new URL with foo bar
        } catch (\Exception $e) {
            $newUrl = 'Error when generating the new URL from the referer.';
        }

        echo $referer.PHP_EOL;
        echo $newUrl;

        // That's it! 😁
    }
}

 Run this snippet  ≪ this.showUnitTest ? this.trans.hide_unit_test : this.trans.show_unit_test ≫  More on Stackoverflow  Random snippet

<?php

declare(strict_types=1);

namespace App\Tests\Controller\Snippets;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;

/**
 * @covers Snippet7Trait
 */
final class Snippet7Test extends KernelTestCase
{
    private RouterInterface $router;

    protected function setUp(): void
    {
        self::bootKernel();
        $this->router = self::$container->get('router');
    }

    /**
     * @covers Snippet7Trait::snippet7
     */
    public function testSnippet7(): void
    {
        $referer = '/en/snippets/get-the-routing-information-of-the-referer';
        $refererPathInfo = Request::create($referer)->getPathInfo();
        $routeInfos = $this->router->match($refererPathInfo);
        $refererRoute = $routeInfos['_route'] ?? '';
        unset($routeInfos['_route'], $routeInfos['_controller']);
        $routeInfos['foo'] = 'bar';
        $newUrl = $this->router->generate($refererRoute, $routeInfos);
        self::assertSame($referer.'?foo=bar', $newUrl);
    }
}