SlideShare a Scribd company logo
API DEVELOPMENT WITH
LARAVEL
@MICHAELPEACOCK
CONFOO, MARCH 2018
WHAT’S IN STORE?
• Walk through building an API with Laravel
• API Routes and Middleware
• API Controllers
• API Resources
• API Authentication
@MICHAELPEACOCK
• Freelance developer & consultant CTO
• Mainly helping early stage SaaS businesses or businesses looking to get into that area
• Part of the @phpne team
• Occasional technical author and speaker
SETUP
LET’S SCAFFOLD A PROJECT
CREATE A NEW LARAVEL PROJECT
composer create-project --prefer-dist laravel/laravel api-development
CREATE A MIGRATION FOR OUR INITIAL MODELS
php artisan make:migration initial_models
API Development with Laravel
API Development with Laravel
API Development with Laravel
RUN OUR DATABASE MIGRATION
php artisan migrate
CREATE A MODEL
php artisan make:model Speaker --factory
API Development with Laravel
API Development with Laravel
API Development with Laravel
API Development with Laravel
CREATE A NEW SEEDER
php artisan make:seeder SponsorSeeder
API Development with Laravel
API Development with Laravel
SEED THE DATABASE
php artisan db:seed
API CONTROLLERS
CREATE AN API CONTROLLER
php artisan make:controller Api/EventController --model=Event --api
API Development with Laravel
CREATE A NEW REQUEST CLASS
php artisan make:request CreateEventRequest
API Development with Laravel
API Development with Laravel
CREATE A NESTED API CONTROLLER
php artisan make:controller Api/EventTalkController
--model=Talk --api --parent=Event
api/events/{event}/talks…
API Development with Laravel
API ROUTES
ROUTING YOUR API REQUESTS
MIDDLEWARE: KERNEL.PHP
RATE LIMITING
throttle:60,1
DYNAMIC RATE LIMITING
API Development with Laravel
API Development with Laravel
ROUTE SERVICE PROVIDER
A MORE SUITABLE NAMESPACE
API Development with Laravel
OUR API SO FAR
VIEWING AN EVENT
VIEWING A LIST OF EVENTS
EVENT PAGINATION
HIDING CERTAIN PROPERTIES
API Development with Laravel
FORM VALIDATION
CAREFUL HOW YOU SET RELATED MODELS PRIOR TO
RETURNING
API Development with Laravel
CAREFUL HOW YOU GET RELATED MODELS
or
API Development with Laravel
API RESOURCES
TRANSFORMING YOUR MODELS AND COLLECTIONS
DO WE NEED API RESOURCES?
• No, but you should use them!
• By default, models and collections are converted to json anyway
• Why should you use them?
• Separation of model and API response
• Makes versioning easier
• Greater flexibility in terms of what is returned
CREATE A NEW RESOURCE
php artisan make:resource Event
API Development with Laravel
API Development with Laravel
API Development with Laravel
API Development with Laravel
WITHOUT DATA WRAPPING
API Development with Laravel
CUSTOMISING DATA WRAPPING
COLLECTION
OurResource::collection($collection);
CREATE NEW RESOURCES FOR COLLECTIONS
php artisan make:resource Events --collection
php artisan make:resource EventCollection
API Development with Laravel
API Development with Laravel
API Development with Laravel
NESTED COLLECTION
API Development with Laravel
WRAPPING NESTED RESOURCES
API Development with Laravel
IT WON’T DOUBLE NEST
NESTED PAGINATION
• Doesn’t seem to be supported
• I’d hoped that if an event had talks, I could paginate the talks, however the pagination meta data is
dropped from the response when it’s a nested item
CUSTOMISING THE LINKS & META DATA
API Development with Laravel
API Development with Laravel
API Development with Laravel
API Development with Laravel
CONDITIONALS: RELATIONSHIPS
CONDITIONALS: ATTRIBUTES
API Development with Laravel
API AUTHENTICATION
INSTALL AND SETUP PASSPORT
composer require laravel/passport
php artisan migrate
php artisan passport:install
HASAPITOKENS
PASSPORT ROUTES
API Development with Laravel
API Development with Laravel
API BASED
REGISTRATION
API AUTHENTICATION
Authorization: Bearer YourAccessTokenHere
API Development with Laravel
API Development with Laravel
API Development with Laravel
THAT’S A WRAP!

More Related Content

API Development with Laravel

Editor's Notes

  1. This talk is going to walk through the creation of a simple API using Laravel. We will build a very basic API for a user group or conference, with support for events, talks, speakers and reviews. We will start out by setting up a fresh Laravel project, creating some models, migrations and seeders, so that we can have some data to play around with right away. We will then take a look at Laravels routing, and how it differentiates API and web requests, and how we can customise this. We will build some API controllers to quickly process an inbound request and return a response. We will customise the response using API resources, and finally we will look at how to enable authentication within the API with Laravel Passport, and some caveats to be aware of.
  2. I’m a freelance developer and consultant CTO mainly helping early stage SaaS start-ups to build products and teams. I’m one of the organisers of PHPNE – a PHP user group NE UK.
  3. In order for us to build an API, we need a basic laravel project, and some models.
  4. The first step is for us to create a new project, which we can quickly do using composer.
  5. We want to model our events, talks, speakers and reviews, so lets start with a migration to store that data in the database. Caveat: Some developers advocate creating a migration per new model (and there are some benefits to that which I’ll come to in a moment), but I often find with a new project, especially if there are related models with cyclical relationships, it’s a little easier to do it all in one go. Jump to the migration.
  6. Events, and sponsors.
  7. Speakers and event sponsors.
  8. Talks and reviews. Note on reviews – intentionally allowing user and non-user reviews for the purposes of dynamic API response
  9. We also want to create a model to represent the data in our application. The factory flag also tells Laravel we want to make a factory, which is used to quickly create fake instances of this model for testing or seeding purposes. We could also use the –m flag to tell Laravel to create a migration at the same time. Jump to the model, and then the factory.
  10. Scaffolded model
  11. Fleshed out model
  12. Scaffolded Factory
  13. Fleshed out factory
  14. We can then make a seeder which will be used to populate a fresh install of the project with data.
  15. Seed scaffolding
  16. Implemented seeder
  17. Once we have seeders in place and tied to our database seeder, we can then seed our database with data. Personally, if I have live seed data, such as pre-defined categories, countries, currencies or other things which a system needs from day 1, I’d put them in a migration, and use the seeder purely for seeding a test or development database.
  18. Laravel has a concept of a resource controller, which is a controller scaffolded out for list, create, edit, delete, view operations on a particular model. They have methods for index, create, store, edit, update and destroy. Edit and Create are methods to show the create and edit form and in the context of an API they don’t serve a purpose. To make our lives even easier still, Laravel has support for what it calls API controllers, which essentially doesn’t scaffold these surplus methods.
  19. Creating an API controller involves the make:controller command, with the name of the class we want to create, the model we want to bind it to, and the api option to tell it that this resource controller is an API controller.
  20. API Controller scaffolding
  21. As we want to be able to create events and other things in our system, we need a request class to validatate the users request. The make:request command will create a request class for us, and then we just fill it out, and type hint it to the controller action where we want to use it.
  22. Request scaffolding. Implementation follows.
  23. Implemented rules
  24. Resource and API controllers can scaffolded to be nested under a single parent, by providing the parent model via the parent flag. In this instance, the controller will be scaffolded so that the methods are passed the parent model before the child model. The scaffolding is limnited to one parent, however if you are manually creating API controllers you can nest further down if you like.
  25. API Controller with model and parent, scaffolding
  26. One useful concept with Laravel when it comes to routes is middleware. Middleware are specific blocks of code which run once a route is matched, but before control is delegated to the matching route. In some cases they are purely used to modify the request, such as the bindings middleware are used to bind our models to our route parameters. In other cases, the middleware might reject a request – such as the CSRF middleware, which checks for the existance of a correct CSRF token. Useful middleware is pre-configured and grouped into middleware groups, which means that middleware which is useful in the context of a web request is automatically included on web routes, and API related middleware is automatically included on the API routes.
  27. By default, we have the throttle middleware enabled. The format of this configuration is 60 requests per minute. If someone exceeds this limit, then their requests will be throttled.
  28. Dynamic rate limiting allows us to customize the limit based upon an attribute associated with the authenticated user. This example will limit requests based off the users rate_limit parameter per minute. This is new in Laravel 5.6.
  29. Rate limiting information is helpfully returned to the user in the response headers. Here you can see we have a limit of 60 requests, and we have 57 requests remaining.
  30. Once we hit the limit, Laravel will automatically reject the request with a 429 response, and also returns a timestamp for when our rate limit will be reset.
  31. By default, the route service provider does some helpful setup for our API routes. It tells Laravel that the routes should all be prefixed with /api, that they should run the API middleware which we looked at before, that the controllers are within a particular namespace and that they have their own routes file.
  32. Given we probably want to have our API controllers in a separate location to our web controllers, it makes sense to change the namespace to look in the API directory.
  33. Since we have built some resource / API controllers, we can enable them with the resource route helper, simply pointing to the controller, and specifying the route prefix we want to use.
  34. So far we haven’t really done much API specific work. We have chosen some API routes, we are returning models instead of views, and we are omitting some standard CRUD methods which would typically display a form. That’s the only differences we have made so far with regards to what we have put together. Lets see what this looks like.
  35. Scaffolded event resource
  36. Using the resource.
  37. This is the DEFAULT resource view, just all of the properties, excluding hidden ones. However we can customise the resource. Example of a customised one on the following slide.
  38. While the resource doesn’t extend our model, it has access to the models properties as if they were its own. We just access them in the toArray method
  39. By default, Laravel wraps the response under an attribute called data. This is primarily because with older browsers there are security issues with exposing API data as the root attributes in your response (I’m not sure but this might be limited to arrays, and not objects). In this situation, with older browsers, its possible for a third party site to load in your API via a JS tag and extract data, which if for some reason your API maintained authenticated state (or maybe its an AJAX response which allows authenticated state) – subsequently stealing data from the API. By having this as an object, it isn’t possible to do this. If we return a collection by default, then this would be an array, so the data wrapping, keeps our data out of the root response. The withoutWrapping method only affects the outer-most response and will not remove data keys that you manually add to your own resource collections. Pagination will ignore this, because there is meta data the collection has to be one level in, in order for the meta data and links to be stored
  40. We can also customise the data wrapping if we want, changing the word data for something else. Useful if you are porting over a legacy API, or just want a more descriptive response.
  41. We can also chose to customise the meta data, and other root level elements, for situations where the resource being returned is the root level resource using with with() method. This adds data to the response, but only if it isn’t a nested resource.
  42. Earlier, we noticed how the (non resource) response would vary depending on how related models were loaded. If we want to maintain this approach, we can use conditionals in our responses.
  43. We can also put this in our Request class (maybe jump to the code), within there we can check to see if there is a user associated with the request, if there is we check that the user has the correct permissions. If not then we don’t let them review.