Skip to content

Instantly share code, notes, and snippets.

@nasrulhazim
Forked from claytonrcarter/README.md
Created February 15, 2018 05:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nasrulhazim/4102311e78aaae815865a992555f483d to your computer and use it in GitHub Desktop.
Save nasrulhazim/4102311e78aaae815865a992555f483d 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);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment