This page is part of our Symfony Live 2011 talk
about REST web services with symfony and
Symfony2. There are major
differences between the two frameworks, which can both be
listed as RESTful, even if their REST implementations are very
The aim of this page is to compare the frameworks best practices and
out-of-the-box solutions for creating a REST web service over HTTP. Learn
how symfony 1 and Symfony2 can help you with the routing,
the validation, the output formats and
The Router component is quite simpler than the symfony one's, it's all
about matching pattern and generating URL ONLY.
Here is the configuration file, nothing much to say about it, but look
at the _controller parameter: no more action / module -
you just declare a callable controller. It can be anything, even a
static method from a custom class.
Take a look at ParamConverter
if you want a sfDoctrineRoute-like input.
The Validation process has been entirely rebuilt from symfony 1 to
There are two validators declarations: one in sfForm,
the other in Doctrine. They can't work together, so we usually use
the sfValidators from sfForm.
$pony_form = new PonyForm();
// You can save the Pony here
Using the annotations, you can define the fields validators directly
in Doctrine entities or in any other class. You can also declare
validators in separate YAML, XML or
PHP files. Write once, use everywhere!
There is no true serializer concept in symfony, but Symfony2 introduces
a Serializer component. Here is how to encode XML Ponies
with both versions of the framework.
As there is no Serializer component, we must use the
Doctrine Dumper. It works fine but we will not be able to customise
$query = // New DoctrineQuery fetching some ponies!
It is rather quick and dirty, there is no CDATA, no
namespace... But it is the only solution out of the box.
For decoding a payload, you may use Doctrine_Parser::load
Introducing the new Serializer component, composed of
Normalizers and Encoders:
the normalizer transforms Entities into PHP arrays,
and the encoder... encodes them into JSON or XML (or whatever).
// Init the Serializer
$serializer = new Serializer\Serializer();
$serializer->setEncoder('xml', new Serializer\Encoder\XmlEncoder());
$xml_pony = $serializer->encode($pony, 'xml'); // Return an XML string
$pony_from_xml = $serializer->denormalizeObject( // Return a Pony instance
$serializer->decode($xml_pony, 'xml'), // Return an array from the XML
Caching your Resources
Caching is really important. You must set it up, even for a short time.
Your server charge will definitely thank you.
The full page cache is set in each application cache.yml
and activated in settings.yml. Resources will be stored
on the server hard drive, but you can specify a custom store, like
Memcached for instance.
Off course, only the safe method GET gets stored into
the cache. The invalidation is kind of easy too :
if ($cache = $this->getContext()->getViewCacheManager())
The Symfony2 cache is... HTTP. In fact, there is no
full page cache inside Symfony2. Check out the
or the code below - the secret is to use a reverse-proxy, and to
correctly set the HTTP expiration and validation headers. No
The cache proxy will store this resource for 120 seconds. The downside
is that there is no invalidation method. Therefore, it is possible to
associate the expiration to a validation method, which can reduce the
$response->setETag(\md5(\serialize($pony))); // Should be a method in Pony
// return the 304 Response immediately
// do some stuff and return a full Response