Hiking on Laravel Routes

Hiking on Laravel Routes
Photo by Michele De Pascalis / Unsplash

To manage a complex navigation behavior (like: server side rendered panels dynamically loaded and stacked in the web page) I had to pass a state across different server side requests to differentiate the cases in which I just wanted to navigate the hierarchy and the case in which I need to dive deep into the same hierarchy to find and select a specific item. But such a state was related just to the navigation/selection operation, not to the whole session (nor to other possibile requests dynamically coming from the same web page), so I had to define it using a dedicated GET parameter. And I'm lazy enough that I didn't want to manually handle that parameter and to chain it in subsequent calls: when the first request having the (for example) selecting parameter comes, all links in the returned page should have the same selecting parameter in all internally generated routes.

So I had to discover some way to manipulate once all URLs generated by the route() helper, to attach my own hijacking logic.

In AppServiceProvider I've replaced the singleton binded to the url identifier with my own implementation.

use App\Helpers\StateUrlGenerator;

public function register()
{
  $this->app->singleton('url', function ($app) {
    $routes = $app['router']->getRoutes();
    $rebind = $app->rebinding('request', function ($app, $request) {
      $app['url']->setRequest($request);
    });

    return new StateUrlGenerator($routes, $rebind, $app['config']['app.asset_url']);
  });
}

The StateUrlGenerator class is just an extension of the native UrlGenerator overwriting a single function: the one allocating the internal routeGenerator, which is replaced with the custom one.

<?php

namespace App\Helpers;

use Illuminate\Routing\UrlGenerator;

class StateUrlGenerator extends UrlGenerator
{
  protected function routeUrl()
  {
    if (! $this->routeGenerator) {
      $this->routeGenerator = new StateRouteUrlGenerator($this, $this->request);
    }

    return $this->routeGenerator;
  }
}

The actual URL generator extends the native one, and may be used to inject own custom variables to the $parameters payload.

<?php

namespace App\Helpers;

use Illuminate\Routing\RouteUrlGenerator;

class StateRouteUrlGenerator extends RouteUrlGenerator
{
  public function to($route, $parameters = [], $absolute = false)
  {
    /*
      Put your custom elements in $parameters
    */

    return parent::to($route, $parameters, $absolute);
  }
}

At this point, I can push variables from the Request (accessed through the request() helper) or any other variable guessed from the session, the database, or anything else. Those will be appended to any URL generated with route() or similar functions usually used to link things together.