Getting Started with FOSUserBundle


Let's get started with FOSUserBundle. By the end of this video you will have:

  • installed FOSUserBundle into a Symfony2 project
  • updated your database to store your new User entities
  • created a brand new User
  • learned about the various Roles a User may have, including ROLE_USER

Once you go beyond the very basic CRUD-style site you might build whilst learning Symfony2, you inevitably start needing the same sorts of modules (or bundles in Symfony-speak) regardless of the type of web site you are building.

User registration and management is perhaps the most common of these modules / bundles.

FOSUserBundle solves this common problem.

Right out of the box it gives us a fully working set of URLs / routes for Registration, Password Resets, Profile Management, along with Login and Log out.

I use FOSUserBundle right here on CodeReviewVideos. I have added some customisation, but everything from Registration through to managing your Profile is part of FOSUserBundle.

I use FOSUserBundle on every other project where I need User management. It's awesome. It installs in a fairly simple manner, and once it is in, it just kinda works.

If you haven't already done so, follow along with the official guide on Getting Started With FOSUserBundle. If you are adding FOSUserBundle into an existing project, be sure to make a full backup of your database before adding in the new User entity data.

When copying over the configuration for app/config/security.yml from the official docs, be sure to copy in your dev firewall and any other customisations you may have made.

I won't cover the installation procedure past this point as it really is largely just copy and paste from the docs.

User Management

Once you have installed and done the essential configuration for FOSUserBundle, the next likely step you will want to take is to create your first User account.

As part of the installation procedure, you will have created a User class (or your own variant) likely extending FOS\UserBundle\Model\User, and ultimately implementing FOS\UserBundle\Model\UserInterface.

To get the most from this video, ideally you will follow along with your own installation. If at any point so far you are thinking... Huh? Then please follow the official installation instructions before continuing.

Once you have created your User entity, you will have created the associated MySQL database table in which to persist your Users. If you are using MongoDB or other databases, this process should largely be similar.

To keep your User data secure, your FOSUserBundle's User class has been configured to encode all passwords with bcrypt:

# http://symfony.com/doc/current/bundles/FOSUserBundle/index.html#step-4-configure-your-application-s-security-yml

# app/config/security.yml
security:
    encoders:
        FOS\UserBundle\Model\UserInterface: bcrypt

This stops you from (easily) adding in a new User directly to your MySQL table.

Thankfully, FOSUserBundle comes with a set of command line tools to manage your application's Users.

We can begin by adding in a new user:

php app/console fos:user:create 
# or
php app/console fos:user:create codereview
# or 
php app/console fos:user:create codereview chris@codereviewvideos.com
# or 
php app/console fos:user:create codereview chris@codereviewvideos.com a_password_here

Note: Any User objects that you create this way will be automatically set to enabled.

All are valid ways to use the command. Each of the three arguments (username, email, password) are optional. We will be interactively prompted to add in any arguments we don't supply.

Hint: If adding User data via the command line like in the above example, put a space before you command so the information is not saved in your terminal history, revealing any sensitive password / user information. This only works on more recent unix-y systems afaik. Better still, leave the password off and use the interactive prompt.

Symfony is helpful in that whilst there are often lots of available commands available to us, you needn't remember them all as your command line will help you. Can't remember all the available commands? Just type in php app/console and the full list of available commands will be printed out for your reference.

In the case of FOSUserBundle, we can simply type: php app/console fos, and hit return, and you will see something similar to:

[InvalidArgumentException]
Command "fos" is not defined.
Did you mean one of these?
    fos:user:change-password
    fos:user:deactivate
    fos:user:activate
    fos:user:promote
    fos:user:create
    fos:user:demote

Again, all these are explained on the command line tools documentation page.

Being able to change a User's password from the command line is very helpful.

What, perhaps, is less obvious is the usefulness of promote and demote.

This command allows us to add and remove Roles from a given User. We haven't discussed Roles yet, but will do so shortly.

If we were to want to add a specific Role to a given User at this point, we would need to manually serialize and deserialize the $roles property of our User object. This is a bit nasty. So instead, FOSUserBundle promote and demote give us a very quick way to add or remove Roles from our User object, direct from the command line.

The following would give the Role of ROLE_ADMIN to a user named some_admin_user:

php app/console fos:user:promote some_admin_user ROLE_ADMIN

Alternatively, you could give the Role of ROLE_SUPER_ADMIN to the user: some_superadmin_user by:

php app/console fos:user:promote some_superadmin_user --super

Likewise, we can quickly remove a specific Role by one of the following:

php app/console fos:user:demote some_admin_user ROLE_ADMIN

# and / or

php app/console fos:user:demote some_superadmin_user --super

Both are incredibly handy commands to know about particularly during the application development phase of a project.

Whose Role Is It Anyway?

All this talk of promoting and demoting User accounts from a given Role, and so far, no one has told us what a Role actually is!

Firstly, it's always helpful to give the official documentation a read where possible.

If you have configured and are using FOSUserBundle, whenever a User successfully logs in, they are going to get the Role of ROLE_USER.

This is important to understand, as you don't actually assign the Role of ROLE_USER explicitly. This can be confusing.

When we created our first User, we saw that in the database, the User's Roles column was empty. We could easily add / remove Roles by way of promote and demote, but we never added ROLE_USER. Yet as soon as we log in, we get the Role of ROLE_USER.

Where Do Roles Come From?

The next confusing point - ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH, etc - where on Earth are these things coming from?

Well, they are made up.

Symfony comes with some suggested roles - ROLE_USER, ROLE_ADMIN, ROLE_SUPER_ADMIN, etc - but we don't have to use them. We could even change from using ROLE_USER if we really wished. My advice is don't do that, however, as software development is already hard enough, without creating more needless headaches for ourselves.

We are completely free to make up and add any, and as many Roles as we want too.

We could create ROLE_CAN_COMMENT or ROLE_EATS_CHIPS or anything we like.

By giving Roles to our Users, we could then restrict parts of our Symfony application to only Users who have the given Role.

The most common use case for this would be to restrict certain paths in our application to only Users with ROLE_ADMIN, or similar:

# app/config/security.yml
security:
    access_control:
        - { path: ^/admin, roles: ROLE_ADMIN }

But we are just as free to do something like:

# app/config/security.yml
security:
    access_control:
        - { path: /add-comment$, roles: ROLE_CAN_COMMENT }

Notice, the path parameter uses regular expressions. In the /add-comment$ example I have omitted the ^ from the start of the path, which means any URL ending in /add-comment would be restricted to Users with the Role of ROLE_CAN_COMMENT.

The concept of access_control is outside the scope of this video. If interested, this section of the docs is a great place to start.

Symfony will also allow you to restrict Controller actions and other blocks of code according to whether or not the given User has a specific Role. See here for more.

Role Hierarchy

During set-up of FOSUserBundle, we also added in the following:

# app/config/security.yml
security:
    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

By providing a role_hierarchy, we can inherit Roles depending on the Role we have.

If our User has ROLE_USER, then they don't inherit / get any other Roles.

If our User has ROLE_ADMIN, then they would also be a ROLE_USER, according to our role_hierarchy.

Likewise, ROLE_SUPER_ADMIN inherits ROLE_ADMIN, which in turn, inherits ROLE_USER.

We can also add in arrays of Roles. There's no point in me regurgitating the documentation - if you want to know more, this section of the official docs will be of help.

Code For This Course

Get the code for this course.

Episodes