Course Overview & API Walkthrough


In this video we are going to take an informal look at the RESTful API we will be creating throughout this course.

We will briefly touch on how FOSUserBundle, FOSRESTBundle, and LexikJWTBundle work together to form the foundations of our finished system.

We will touch on the differences in routing between this implementation and a standard FOSUserBundle setup. Don't worry, we will dive deeper into each of these changes - and the reasons behind them - as we work through the course.

The reasoning for needing routing changes is that the implementation supplied with FOSUserBundle is designed to work with Twig / HTML. We cannot "flip a switch" and suddenly have a JSON approach instead.

To change this, we must override the controllers provided by FOSUserBundle.

During the initial design phase of this tutorial I tried numerous approaches to avoid this. Unfortunately, I came unstuck at various points along each alternative attempt. If you know of a better solution to this problem, do let me know. I am always eager to learn and improve.

The primary reason I didn't want to have to re-implement the controller logic is in the fact that by doing so, I have now taken ownership of maintaining these various controllers, should their FOSUserBundle-provided implementation change for any reason.

This is an obvious downside, but there are some ways to mitigate this problem - as we will see towards the end of this course.

Routing Changes

Whilst this project isn't the most visually interesting thing we have ever done here at CodeReviewVideos, it is never the less one of the most important (in my opinion).

One way we can see stuff happen is to evaluate a before and after of the routes available in our Symfony application.

Here are the routes provided by FOSUserBundle:

 Name                              Method   Scheme Host Path
 fos_user_security_login           GET|POST ANY    ANY  /login
 fos_user_security_check           POST     ANY    ANY  /login_check
 fos_user_security_logout          GET      ANY    ANY  /logout
 fos_user_profile_show             GET      ANY    ANY  /profile/
 fos_user_profile_edit             GET|POST ANY    ANY  /profile/edit
 fos_user_registration_register    GET|POST ANY    ANY  /register/
 fos_user_registration_check_email GET      ANY    ANY  /register/check-email
 fos_user_registration_confirm     GET      ANY    ANY  /register/confirm/{token}
 fos_user_registration_confirmed   GET      ANY    ANY  /register/confirmed
 fos_user_resetting_request        GET      ANY    ANY  /resetting/request
 fos_user_resetting_send_email     POST     ANY    ANY  /resetting/send-email
 fos_user_resetting_check_email    GET      ANY    ANY  /resetting/check-email
 fos_user_resetting_reset          GET|POST ANY    ANY  /resetting/reset/{token}
 fos_user_change_password          GET|POST ANY    ANY  /profile/change-password

And here are the routes you will have at the end of this course:

  api_login_check            ANY      ANY      ANY    /login_check
  post_login                 POST     ANY      ANY    /login
  request_password_reset     POST     ANY      ANY    /password/reset/request
  confirm_password_reset     POST     ANY      ANY    /password/reset/confirm
  change_password            POST     ANY      ANY    /password/{user}/change
  get_profile                GET      ANY      ANY    /profile/{user}
  put_profile                PUT      ANY      ANY    /profile/{user}
  patch_profile              PATCH    ANY      ANY    /profile/{user}
  register_registration      POST     ANY      ANY    /register

There are some interesting changes here, and we will cover each in the respective video(s).

Just one point to address - the omission of the logout link isn't a mistake. To log out, we simply no longer use the token - deleting from the browser's localStorage as an example. I am taking the approach that this is not a concern of the back end / Symfony.

Test First

We will be using Behat for testing our API.

For each set of routes (login, profile, password, and register) we will start by writing out the Behat feature specification, and then write enough code that we change each red failing test to a nice green passing test.

Not only will this provide us with confidence that our system behaves as expected, but also it will serve as working documentation for any developers new to our project. It also makes changing things all the more reliable.

A nice side effect of writing our tests in this manner is that we can work on our login and registration system in a way that goes from easiest steps to the more difficult steps, in a way we can control.

For example, if we had to start off by implementing Registration before we could even test Login, then we would likely want to throw in the towel and slope off to read Reddit instead.

By adding tests that create users in our database before we have implemented Registration, we can instead start by working on the Login flow, then modify our existing profile, ensure we can change our user's password, and once all these things work, Registration will be much easier. Not to mention, once a user registers they will have a nice, working system to interact with.

Where Do We Go From Here?

It's the first video in this series so logically we go onwards to actually implementing all of these routes.

However, to discuss the wider picture, where can we go with this implementation?

Well, this could serve as the back end for any other system that can interact with our user login and registration system via HTTP.

This is currently serving as the foundation of the new back end for CodeReviewVideos. There likely will be tweaks to this, particularly around billing (as in, integration with Stripe) and hooking into some queuing system (such as RabbitMQ).

Personally I currently favour React and Redux as my front end weapons of choice, so will be demonstrating how to create a front end for this back end in the very next series. You could just as easily write a front end in Angular 1, or Angular 2, Ember, Vue, or the ever growing multitude of other available options.

Code For This Course

Get the code for this course.

Episodes