Share named routes between Laravel and Javascript
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->getUri();
}
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);
}
}
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.
RouteJson.php
Copy RouteJson.php
into your app as app/Console/Commands/RouteJson.php
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
];
route()
helperCopy route.js
into your app as resources/assets/js/route.js
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.