Skip to content

Instantly share code, notes, and snippets.

@claytonrcarter
Last active June 8, 2023 05:42
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save claytonrcarter/e1509fd94a5965f3def522c5328f45d0 to your computer and use it in GitHub Desktop.
Save claytonrcarter/e1509fd94a5965f3def522c5328f45d0 to your computer and use it in GitHub Desktop.
Share named routes between Laravel and Javascript

Share named routes between Laravel and Javascript

This is a 2-part technique to share named routes between Laravel and Javascript. It uses a custom artisan command to export your named routes to JSON, and a Javascript route() helper to lookup the route and fill in any parameters. Written for Laravel 5.3; not tested in 5.4.

Installation

1. Install RouteJson.php

Copy RouteJson.php into your app as app/Console/Commands/RouteJson.php

2. Edit Kernel.php

Edit the app/Console/Kernel.php file to make sure that Commands\RouteJson::class is included in the $commands array. For example, the $commands in my Kernel.php looks like this:

/**
 * The Artisan commands provided by your application.
 *
 * @var array
 */
protected $commands = [
    Commands\RouteJson::class
];

3. Install the Javascript route() helper

Copy route.js into your app as resources/assets/js/route.js

Usage

Issue the command php artisan route:json to export your routes to the file resources/assets/js/routes.json. Then, in your Javascript code, you can import route from './route.js' and use the route() helper very similarly to the PHP version in Laravel:

import route from './route.js'; // or '../route.js', '../../route.js', etc

console.log( route( 'user.note.store', { user: 123 } )); // -> /user/123/note

Optional route parameters that aren't passed in the paramerter object will be discarded, but mandatory route parameters that aren't passed in will be left in the returned URI. No error or warning is generated if there are leftover mandatory parameters.

It's not perfect, but it's worked for me. Maybe it will work for you.

import routes from './routes.json'
export default function( routeName, replacements = {} ) {
var uri = routes[routeName]
if ( uri === undefined )
console.error('Cannot find route:', routeName )
Object.keys(replacements)
.forEach( key => uri = uri.replace( new RegExp( '{' + key + '\\??}' ), replacements[key] ))
// finally, remove any leftover optional parameters (inc leading slash)
return uri.replace( /\/{[a-zA-Z]+\?}/, '' )
}
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Route;
class RouteJson extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'route:json';
/**
* The console command description.
*
* @var string
*/
protected $description = 'My route json command';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$routes = $this->generateRoutes();
$this->writeJson( $routes );
return;
}
public function generateRoutes()
{
$routes = [];
foreach ( Route::getRoutes()->getRoutes() as $route) {
if ( is_null( $route->getName() ))
continue;
if ( isset( $routes[$route->getName()] ))
$this->comment("Overwriting duplicate named route: " . $route->getName());
$routes[$route->getName()] = "/" . $route->uri();
}
return $routes;
}
protected function writeJson( $routes ) {
$filename = 'resources/assets/js/routes.json';
if (!$handle = fopen($filename, 'w')) {
$this->error( "Cannot open file: $filename" );
return;
}
// Write $somecontent to our opened file.
if ( fwrite( $handle, json_encode($routes) ) === FALSE) {
$this->error( "Cannot write to file: $filename" );
return;
}
$this->info("Wrote routes to: $filename");
fclose($handle);
}
}
@IlyasDeckers
Copy link

IlyasDeckers commented Jun 14, 2017

You just made my day 👍
Just one thing, in generateRoutes you use $route->getUri this threw the folowing error in Laravel 5.4

Call to undefined method Illuminate\Routing\Route::getUri()

You should change it to $route->uri()`

@claytonrcarter
Copy link
Author

Thanks @IlyasDeckers, just fixed it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment