Simple Symfony 3 RESTful API Setup
In this video we are going to cover all the setup and configuration changes required to start using our Symfony 3 installation as a RESTful API. To achieve this we will make use of a number of third party bundles:
- FOS REST Bundle
- JMS Serializer Bundle
- Nelmio CORS Bundle
- Nelmio API Doc Bundle
And we will continue to include Will Durand's Faker Bundle.
If you'd rather just see the code directly, you can do so by visiting the GitHub Repo.
Some points to note here:
We are going to use FOS REST Bundle at version 1.7. There are many changes coming shortly in version 2.0, but this is still under active development. I have opted to keep with a stable version for this project, but would recommend trying 2.0 if you are not building a 'serious' project. There are many fixes that make life that little bit easier for you.
The relevant part of the composer.json
file would be :
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.1.*",
"doctrine/orm": "^2.5",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"symfony/swiftmailer-bundle": "^2.3",
"symfony/monolog-bundle": "^2.8",
"symfony/polyfill-apcu": "^1.0",
"sensio/distribution-bundle": "^5.0",
"sensio/framework-extra-bundle": "^3.0.2",
"incenteev/composer-parameter-handler": "^2.0",
"nelmio/cors-bundle": "^1.4",
"nelmio/api-doc-bundle": "^2.11",
"friendsofsymfony/rest-bundle": "^1.7",
"jms/serializer-bundle": "^1.1",
"willdurand/faker-bundle": "^1.3"
},
If you would rather go with the later version of FOS REST Bundle, update accordingly:
"friendsofsymfony/rest-bundle": "^2.0@dev",
By using the @dev
tag you can avoid having to change your entire project's stability setting. I blogged a little more about updating here.
We're making use of JMS Serializer to enable - unsurprisingly - serialisation and deserialisation in our project. This is how we can easily transform JSON into PHP / Symfony-friendly entities, and back again.
Nelmio CORS bundle enables us to easily configure Cross-Origin Resource Sharing headers, which will make communicating with our API from our front end much simpler.
Lastly, Nelmio API Docs bundle is a little uncertain at this point. There was mention of the bundle being deprecated by its maintainer - Will Durand. Judging from the reaction to the Twitter poll, it seems its future is secure in the short term, but this is something to be aware of in the longer term. I currently don't have an alternative to this, but if you know of one, please do leave a comment below.
The config for all these bundles is as follows:
// /app/AppKernel.php
class AppKernel extends Kernel
{
public function registerBundles()
{
// * snip *
new FOS\RestBundle\FOSRestBundle(),
new Nelmio\CorsBundle\NelmioCorsBundle(),
new Nelmio\ApiDocBundle\NelmioApiDocBundle(),
new JMS\SerializerBundle\JMSSerializerBundle(),
And:
# /app/config/config.yml
# Nelmio CORS
nelmio_cors:
defaults:
allow_origin: ["%cors_allow_origin%"]
allow_methods: ["POST", "PUT", "GET", "DELETE", "OPTIONS"]
allow_headers: ["content-type", "authorization"]
max_age: 3600
paths:
'^/': ~
# Nelmio API Doc
nelmio_api_doc:
sandbox:
accept_type: "application/json"
body_format:
formats: [ "json" ]
default_format: "json"
request_format:
formats:
json: "application/json"
# FOS REST Bundle
fos_rest:
body_listener: true
param_fetcher_listener: true
view:
view_response_listener: 'force'
exception_wrapper_handler: null
formats:
jsonp: true
json: true
xml: false
rss: false
mime_types:
json: ['application/json', 'application/x-json']
jpg: 'image/jpeg'
png: 'image/png'
jsonp_handler: ~
routing_loader:
default_format: json
include_format: false
format_listener:
rules:
- { path: ^/, priorities: [ json, jsonp ], fallback_format: ~, prefer_extension: true }
exception:
enabled: true
Again, note this blog post if using FOS REST Bundle 2.0. There are some config changes to follow.
You should also update your parameters.yml.dist
and parameters.yml
files accordingly:
# /app/config/parameters.yml.dist
# nelmio cors
cors_allow_origin: 'http://localhost'
# nelmio api docs
api_name: 'Your API name'
api_description: 'The full description of your API'
We will need to configure routing:
# /app/config/routing.yml
NelmioApiDocBundle:
resource: "@NelmioApiDocBundle/Resources/config/routing.yml"
prefix: "/doc"
api:
type: rest
resource: "routing_api.yml"
And:
# /app/config/routing_api.yml
blog_posts:
type: rest
resource: AppBundle\Controller\BlogPostsController
Lastly, I've updated the security setup to make this a free-for-all. Again, this is for simplicity, and you should of course, change this as required to suit your needs.
# /app/config/security.yml
security:
# http://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
providers:
in_memory:
memory: ~
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api_docs:
pattern: ^/doc
anonymous: true
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
Seeding Your Database
Back in the very first video we covered how to use Will Durand's Faker Bundle to populate our database with 50 fake entities.
In this and the remaining videos, we are re-using this database, even though this is now a separate project.
If you haven't been following along since the first video, but want to seed your database similarly, be sure to add in the relevant config:
#/app/config/config_dev.yml
bazinga_faker:
orm: doctrine
entities:
AppBundle\Entity\BlogPost:
number: 50
And then run the needed command:
php bin/console faker:populate
That's all the boilerplate out of the way.
In the next video we will start implementing the various API endpoints to make this whole thing come together.