While designing a good RESTful API takes a lot of thought and planning, thanks to application frameworks that have been developed with REST in mind, the nuts and bolts of implementation has never been easier. This how-to explores RESTful API implementation using LaravelTrack this API, an object-oriented MVC framework for PHP that is fast becoming one of the language's most popular frameworks.
Why Laravel?
There are a number of great PHP frameworks that developers can use to build robust PHP applications. Laravel, which is relatively new, has quickly gained a dedicated following. And it's not hard to understand why. Built on top of a number of components from Symfony, one of PHP's most mature frameworks, Laravel adopts many of PHP's newest features, is highly expressive, and features powerful components, including a great templating engine, ORM and command line interface called Artisan.
All of this gives developers a comprehensive toolkit for building applications of all shapes and sizes, and makes Laravel a pleasure to work with.
Installation & Assumptions
Installing Laravel is easy and can be done using Composer, the widely used PHP dependency manager. The Laravel documentation contains detailed installation instructions. This how-to assumes that you have a good understanding of PHP and the MVC model, installed Laravel on a development server, and have familiarized yourself with Laravel's folder structure and conventions.
Getting Started
With Laravel, it is possible to build the simplest of APIs in a matter of minutes. If we open the app/routes.php file, we can very quickly create endpoints for resources using Closures. For instance, add the following to the routes.php:
Route::get('names', function() { return array( 1 => "John", 2 => "Mary", 3 => "Steven" ); });
Assuming Laravel is installed locally and accessible through a web server running on localhost, if you loadhttp://localhost/names in your browser, you should see that the application displays our array as a JSON-encoded string:
{"1":"John","2":"Mary","3":"Steven"}
We can use a similar approach to add additional endpoints. For instance, if we want to create an endpoint that allows us to retrieve the name for a specific ID, we could add the following to routes.php:
Route::get('names/{id}', function($id) { $names = array( 1 => "John", 2 => "Mary", 3 => "Steven" ); return array($id => $names[$id]); });
If we browse to http://localhost/names/2, you should receive the following JSON response:
{"2":"Mary"}
Thus far, we've created endpoints that respond to GET requests. As you might imagine, we can just as easily respond to other types of requests. To respond to a POST request, for instance, just use Route::post instead of Route::get. Laravel also makes it possible to respond to a request regardless of type using Route::any.
Obviously, the examples above are very simple. We're not doing any validation of input or error handling, and we aren't retrieving our data from a real database. But as you can already see, Laravel makes it easy to jump right into building RESTful APIs without first having to reinvent the wheel.
Resource Controllers
In the above examples, we use Closure callbacks to define responses directly in our routes.php file. Of course, when building a real application, you'll probably want to move your response logic into controllers to keep your code organized.
As you gain familiarity with Laravel, you'll quickly notice that its creator, Taylor Otwell, has made it incredibly easy and efficient to implement common functionality and perform certain tasks. This is true when it comes to building RESTful applications.
When implementing a RESTful API, we could define routes for all of the actions associated with a resource. Or we could let Laravel do the heavy lifting for us and utilize Resource Controllers.
To start, we'll use Laravel's command line tool, Artisan, to create a new controller by typing the following at the command line:
php artisan controller:make NameController
This creates a file, NameController.php in the app/controllers directory, which we'll take a look at in a minute.
First, however, we'll remove the code we added earlier to our routes.php file and replace it with:
Route::resource('names', 'NameController');
Note that instead of using Route::get or Route::post, we used Route::resource. This allows us to define multiple routes for the name resource for all of the major HTTP methods (GET, POST, PUT and DELETE) without having to manually define each of them.
If you open up the generated file app/controllers/NameController.php, you'll notice that it has already stubbed the methods. For example, here's some of the code in the file:
/** * Display a listing of the resource * * @return Response */ public function index() { // } /** * Store a newly created resource in storage * * @return Response */ public function store() { // }
For more information about all the stubs Laravel creates for you, consult the Laravel documentation. In the meantime, we can add some of our logic to one of the stubs. For example:
/** * Display a listing of the resource * * @return Response */ public function index() { return array( 1 => "John", 2 => "Mary", 3 => "Steven" ); }
If you refresh http://localhost/names in your browser, you'll see that the same JSON list containing our names is displayed, but now we're employing the MVC pattern and are responding to the request using our controller and not a Closure.
At this point, you might be asking what happens if you have a resource that doesn't need to respond to all of the HTTP methods. Fortunately, Laravel makes it easy to handle these situations. The Artisan command for creating a controller gives us the ability to specify the actions we want stubbed. For instance, if we only need an index function for a resource, we would use:
php artisan controller:make NameController --only=index
And then we can instruct the route to respond only to the index action:
Route::resource('names', 'NameController', array('only' => array('index')));
Authentication
Authentication is often a critical component of an API, and there are a lot of different ways to implement authentication. We can implement any of them using Laravel but for now, let's use HTTP Basic authentication.
In routes.php, we'll modify the route associated with our Resource Controller:
Route::resource('names', array('before' => 'basic.once'), 'NameController');
Next, open app/filters.php and add the following code:
Route::filter('basic.once', function() { return Auth::onceBasic(); });
What we have done is add a filter that is applied before the application handles a request to the names route. The filter code we added to filters.php file utilizes a method in Laravel's authentication class to ensure that the user is authorized to access the resource in question using stateless HTTP Basic authentication. If authentication fails, the filter catches this before the code that provides our response is executed.
Note that for HTTP Basic authentication to work, you'll need to make sure that you have configured your chosen web server (Apache, Nginx, etc.) appropriately. The Laravel document contains more details.
Comments
Post a Comment