Routing with Laravel 5
Sometimes we need a generic solution to serving clients models with an API. Today I’ll show how this can be done using the PHP framework, Laravel 5. I refer to models as entities hereafter, because this application will later be persisting these to Google’s Datastore.
Let’s begin by creating a route group for the API URLs, and another group to capture the entity type being serviced. This is done in the good ol’ routes.php file.
Route::group(['prefix' => 'api'], function () { // ------------ Generic Routes ------------ Route::group(['prefix' => '{entity}'], function () { }); });
Sweet. Now, the next part is my favourite. We’re going to going to resolve the captured entity type into an object instance when a call is made by adding the following lines to the boot() function in RouteServiceProvider.php.
public function boot(Router $router) { $router->bind('entity', function($value) { $class = 'App\Models\' . ucwords($value); return new $class; }); parent::boot($router); }
Adding this bind directive will cause Laravel to bind the entity request parameter in routes.php to the object it’s returning. The object will be injected into scope in the generic controller. Speaking of which, let’s create that.
namespace AppHttpControllers; use IlluminateHttpRequest; use AppHttpControllersController; class EntityController extends Controller { public function fetchById($entity, $id) { $entity = $entity->fetchById($id); return json_encode($entity->getData()); } }
“Woah. Dude. That just made my life so much easier.”
I know. You’re welcome, but we’re not finished yet! Lets add a route that calls fetchById().
Route::group(['prefix' => 'api'], function () { // ------------ Generic Routes ------------ Route::group(['prefix' => '{entity}'], function () { // Fetch Route::get('{id}', 'EntityController@fetchById')->where('id', '[0-9]+'); }); });
Perfect. Now, what about the model? Oh yeah. That. Make sure to nest this file in AppModels (Or whichever folder you specified in the route service provider.
namespace AppModels; class User { public function fetchById($id) { // this part will depend on your persistence implementation! } }
Some closing notes: The boot directive in the route service provider should first check that a class-containing file exists before attempting to instantiate one. I’ve left this part out for the sake of brevity. No one likes a long winded programmer. Except other long winded programmers and deaf people, maybe.