Creating URLs using the route action/handler

By @samuel · 2021-11-01 18:57 (edited)

Creating URLs using the route action/handler

One tip we recently shared on Twitter showed syntax I haven't seen before, but found really interesting.

Basically, you can create redirects like this:

redirect()->action([GitHubController::class, 'callback']);

instead of:

redirect()->route('github.callback');

And for route URLs without redirects, it's url()->action(...) instead of route(...).

The action() approach may seem worse at first due to how verbose it is, but it has two key benefits.

  1. You can click navigate to the action and immediately see it, without having to open your routes file to find where the route is handled
  2. You won't have dead routes

The second problem is something we encountered recently when refactoring the forum's auth. We removed some pages, but our route() references remained the same. No one knew, and then we noticed later when building a separate feature.

With actual callable references, you'd notice this faster (assuming you use a good IDE or some static analysis tools).

I also like the workflow of working on the action itself, and then creating a route to it by referencing the class — without having to look up the route name. Very useful when you're mostly in the action context and not the route context, and just want to create the route quickly, and it also works nicely in controllers — you can do stuff like return redirect()->action([static::class, 'anotherMethod']).

Felt like sharing this because I haven't really seen people use it, but the benefits are clear. Especially when you're used to dealing with action classes/single action controllers and don't use generic CRUD controller resource routes.

  • By @ralphjsmit · 2021-11-09 09:05

    I see that you can also use the shorthand action() function, nice.

    Any idea how this sort of URL looks like? Does it go to the routes file and check whether there's a route that is connected to the same controller?

    • By @samuel · 2021-11-09 13:11

      The URL is the same as the one that route names would generate:

      route('post.create'); // /posts/create
      url()->action([PostController::class, 'create']); // /posts/create
      
      • By @ralphjsmit · 2021-11-09 14:34

        Thanks Samuel!

        (I'm replying here, because Upvoting or Replying on one of the below items is not working for me, because I got a few 500 Livewire errors. I'm using the latest Safari.)

      • By @ralphjsmit · 2021-11-09 13:27

        Okay! So with this routes file:

        Route::get('/user', [PostController::class, 'index'])->name('prefix.user.index');
        

        This:

        route('prefix.user.index'); 
        

        is giving the same as this:

        url()->action([PostController::class, 'index']);
        

        ?

        • By @samuel · 2021-11-09 13:49

          Yeah, should be the same thing. You can test that in tinker to check.