Below you will find pages that utilize the taxonomy term “Symfony2”
A Year With Symfony - End Of Life
TLDR;
- I won’t update A Year With Symfony anymore.
- The e-book is now freely available.
My first book, A Year With Symfony, was well received when I first published it on September 4th. At the time it seemed to be a welcome addition to the official Symfony documentation.
A lot of water has passed under the bridge since then. Several new Symfony components were released and we have now arrived at the next major version, 3.0. In the meantime I published one update of the book: a new chapter about Annotations.
Symfony Catalunya
Everybody is organizing their own PHP conference these days. It’s impossible to “catch ’em all”. There’s conferences clashing, conferences too far away, conferences too much like other conferences, etc.
Then there’s conferences that have never been there before, are quite original and are therefore spark everyone’s imagination. One such a conference is the Symfony Catalunya conference. This “international Symfony event” is being organized by the generally awesome and friend of the community Marc Morera. The concept seems to be pretty simple:
Decoupling from a service locator
Decoupling from a service locator - shouldn’t that be: don’t use a service locator?
Well, not really, since there are lots of valid use cases for using a service locator. The main use case is for making things lazy-loading (yes, you can also use some kind of proxy mechanism for that, but let’s assume you need something simpler). Say we have this EventDispatcher
class:
class EventDispatcher
{
public function __construct(array $listeners)
{
$this->listeners = $listeners;
}
public function dispatch($event)
{
foreach ($this->listeners[$event] as $listener) {
$listener->notify();
}
}
}
Now it appears that some event listeners are rather expensive to instantiate. And, even though it may never be notified (because it listens to a rare event), in order to register any event listener, we need to instantiate it:
Symfony in Barcelona

I just ate a nice pizza at my hotel room in Barcelona. The funny thing is (at least, to a Dutch guy that is): they wouldn’t be able to give me a pizza before 20:00h. At that time in my home country we have long forgotten our desserts, cleaned the dishes and are starting to think about sleeping (just kidding). Anyway, I got the pizza, it was good and now I’m here to write a little report on the things that happened during the last three days.
Unnecessary contrapositions in the new "Symfony Best Practices"
Of course I’m going to write something about the new Symfony Best Practices book that was written by Fabien Potencier, Ryan Weaver and Javier Eguiluz. It got a lot of negative responses, at least in my Twitter feed, and I think it’s a good idea to read Richard Miller’s post for some suggestions on how to deal with an “early preview release” like this and how we can be a bit more positive about it.
Announcements after a year with "A Year With Symfony"
As a follow-up on a previous article I have some announcements to make.
Feedback
A wonderful number of 67 of you have provided very valuable feedback about “A Year With Symfony” - you sure wrote some nice things about my book! Just a small selection of highlights:
Reading “A Year With Symfony” helped to clarify and validate the ideas and structures that I had been developing with my team, along with explaining some of the internals of Symfony that the documentation did not.
Backwards compatible bundle releases
The problem
With a new bundle release you may want to rename services or parameters, make a service private, change some constructor arguments, change the structure of the bundle configuration, etc. Some of these changes may acually be backwards incompatible changes for the users of that bundle. Luckily, the Symfony DependenyInjection component and Config component both provide you with some options to prevent such backwards compatibility (BC) breaks. If you want to know more about backwards compatibility and bundle versioning, please read my previous article on this subject.
Semantic versioning for bundles
A short introduction to semantic versioning
Semantic versioning is an agreement between the user of a package and its maintainer. The maintainer should be able to fix bugs, add new features or completely change the API of the software they provide. At the same time, the user of the package should not be forced to make changes to their own project whenever a package maintainer decides to release a new version.
Exposing resources: from Symfony bundles to packages
Symfony bundles: providing services and exposing resources
When you look at the source code of the Symfony framework, it becomes clear that bundles play two distinct and very different roles: in the first place a bundle is a service container extension: it offers ways to add, modify or remove service definitions and parameters, optionally by means of bundle configuration. This role is represented by the following methods of BundleInterface
:
namespace Symfony\Component\HttpKernel\Bundle;
interface BundleInterface extends ContainerAwareInterface
{
/** Boots the Bundle. */
public function boot();
/** Shutdowns the Bundle. */
public function shutdown();
/** Builds the bundle. */
public function build(ContainerBuilder $container);
/** Returns the container extension that should be implicitly loaded. */
public function getContainerExtension();
...
}
The second role of a bundle is that of a resource provider. When a bundle is registered in the application kernel, it automatically starts to expose all kinds of resources to the application. Think of routing files, controllers, entities, templates, translation files, etc.
Decoupling your (event) system
About interface segregation, dependency inversion and package stability
You are creating a nice reusable package. Inside the package you want to use events to allow others to hook into your own code. You look at several event managers that are available. Since you are somewhat familiar with the Symfony EventDispatcher component already, you decide to add it to your package’s composer.json
:
{
"name": "my/package"
"require": {
"symfony/event-dispatcher": "~2.5"
}
}
Your dependency graph now looks like this:
Symfony2: Event subsystems
Recently I realized that some of the problems I encountered in the past could have been easily solved by what I’m about to explain in this post.
The problem: an event listener introduces a circular reference
The problem is: having a complicated graph of service definitions and their dependencies, which causes a ServiceCircularReferenceException
, saying ‘Circular reference detected for service “…”, path: “… -> … -> …”.’ Somewhere in the path of services that form the circle you then find the event_dispatcher
service. For example: event_dispatcher -> your_event_listener -> some_service -> event_dispatcher
.
Celebrating a year with "A Year With Symfony"
Almost a year ago, on September 4th, in front of a live audience, I published my first book “A Year With Symfony”. Since the first release, well over a 1000 people have read it. In February of this year, I added a new chapter to the book (about annotations).
A third edition?
Flipping through the pages and thinking about how I could best celebrate 1 year and 1000+ readers, I had the following ideas:
Test Symfony2 commands using the Process component and asynchronous assertions
A couple of months ago I wrote about console commands that create a PID file containing the process id (PID) of the PHP process that runs the script. It is very usual to create such a PID file when the process forks itself and thereby creates a daemon which could in theory run forever in the background, with no access to terminal input or output. The process that started the command can take the PID from the PID file and use it to determine whether or not the daemon is still running.
About coding dojos, the Symfony meetup and my new book
Last week was a particularly interesting week. I organised three coding dojos, on three different locations. The first one was at the IPPZ office (one of the companies I’ve worked for), the second one was at the SweetlakePHP meetup in Zoetermeer. The last one was for a group of developers from NOS, a large Dutch news organization. Although that would have been enough, I finished the week with my revised talk “Principles of PHP Package Design” at a meeting of the Dutch Symfony Usergroup in Utrecht…
A Year With Symfony: Bonus chapter is now available!
My first book, A Year With Symfony, has been available since September 4th last year. That’s not even six months ago, but right now it has almost 800 readers already (digital and printed edition combined).
During the past few days I’ve taken the time to write an extra chapter for the book. Consider it as a big thank you to everybody who bought the book! I feel very much supported by the Symfony/PHP community and this really keeps me going.
Symfony2: Add a global option to console commands and generate a PID file
Recently I read the book Signaling PHP by Cal Evans. It’s a short book, yet very affordable and it learned me a couple of things. First of all it explains about how you can “capture” a Ctrl+C
on your long-running command and do some necessary cleanup work before actually terminating the application. In the appendix it also mentioned the interesting concept of a PID file. Such a file is used to store a single process identifier. The file is created by the process itself, to allow other scripts or applications to terminate it. This is especially useful in the context of daemon applications. They can be started by some wrapper script, run in the background, then be monitored and eventually interrupted by an administrator using the SIGINT
signal.
Symfony2: Some things I don't like about Bundles
This article could have been titled “Ten things I hate about bundles”, but that would be too harsh. The things I am going to describe, are not things I hate, but things I don’t like. Besides, when I count them, I don’t come to ten things…
Bundle extension discovery
A Symfony2 bundle can have an Extension
class, which allows you to load service definitions from configuration files or define services for the application in a more dynamic way. From the Symfony documentation:
Looking back at the release of "A Year With Symfony"
A couple of weeks ago the reader count of my first book A Year With Symfony reached the number 365. It seemed to me an appropriate moment to write something about my experiences. In this post, I will not be too humble, and just cite some people who wrote some very nice things about my book on Twitter.
The book was highly anticipated ever since I first wrote something about it on Twitter. Leanpub book pages have a nice feature where users can subscribe to news about the book release.
Symfony2: Console Commands as Services - Why?
As you may have read on the Symfony blog: as of Symfony 2.4 you can register console commands using the service tag console.command
.
What is the big deal, you would say. Well, let’s discover it now. This is how the documentation tells you to write your console commands:
namespace Matthias\ConsoleBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MyCommand extends ContainerAwareCommand
{
protected function configure()
{
$this->setName('my:action');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// do something
}
}
How to make sure your command will be noticed?
Until Symfony 2.4 there were two requirements for your command to be picked up by the console application itself:
Symfony2 & TDD: Testing a Configuration Class
Some of you may already know: I am a big fan of TDD - the real TDD, where you start with a failing test, and only write production code to make that specific test pass (there are three rules concerning this actually).
The TDD approach usually works pretty well for most classes in a project. But there are also classes which are somewhat difficult to test, like your bundle’s extension class, or its configuration class. The usual approach is to skip these classes, or to test them only using integration tests, when they are used in the context of a running application. This means you won’t have all the advantages of unit tests for these “units of code”. Some of the execution paths of the code in these classes may never be executed in a test environment, so errors will be reported when the code is running in production already.
Official book presentation: A Year With Symfony
After working on my book “A Year With Symfony” for four months, I published it yesterday at the Dutch Symfony Usergroup meetup in Amsterdam. It was really great to be able to do this real-time while everybody in the room was looking at the screen waiting for the build process to finish.
The book is hosted on Leanpub, which is a great platform for writing and publishing books. They provide the entire infrastructure. You get a good-looking landing page and they handle all things related to payment.
Why Symfony? Seven Facts
A couple of days ago I was asked to explain myself: “Why Symfony?”. I was reminded of this video - an interview with Fabien Potencier:
Fabien mentions some facts about Symfony that are key to understanding it, as an outsider. These same facts (and some more) will also help you to “sell” Symfony to others.
A New Book About Symfony2: A Year With Symfony
As you may have heard, I’m working on a book for Symfony2 developers. Besides The Book, which is the user documentation for building Symfony applications, some book-like websites and just a few e-books, there are currently no books for intermediate or advanced Symfony developers. My new book, called A Year With Symfony is exactly that.
If you have been reading the documentation and maybe some blog posts, you will want to know how you can get one step further. You wonder how you could structure your application, for it to be maintainable for more than a month. You ask yourself what it would take to write good bundles, which guidelines you and your team should define and follow. You may also question the built-in security measurements and you or your manager would like to know what needs to built on top of them to make a real secure application. A Year With Symfony will help you find an answer to all these questions.
Symfony2: Rich Console Command Output Using AOP
I really like to write console commands for Symfony2 applications. There is something very cool about the Symfony Console Component which always makes me look for new things that I could do from the command line. A very simple command might look like this:
namespace Matthias\BatchProcessBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class BatchProcessCommand extends ContainerAwareCommand
{
protected function configure()
{
$this->setName('matthias:batch-process');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// do something here
...
}
}
Writing good, clean command classes can very problematic: you want to provide detailed output to the user, and tell him what is currently going on, what the result of some action was, or why something failed. You need the console output for this. It is an instance of OutputInterface
and it is provided as the second argument of the command’s execute()
method. The body of this method will usually look like this:
Symfony2: Defining and dispatching custom form events
The Symfony Form Component has an architecture that keeps inspiring me. It supports horizontal and vertical inheritance and it has a solid event system on a very fine-grained level. In this post I would like to explain how you can expand the event system with your own events. As an example., I will create a new event type used for indicating that the bound form is valid.
Using event listeners and event subscribers with forms
As you can read in a Symfony Cookbook article you can already hook into special form events, defined in Symfony\Component\Form\FormEvents
:
Symfony2: Security enhancements part II
Part II of this series is all about validating the user’s session. You can find Part I here, if you missed it.
Collect Failed Authentication Attempts
Now and then a user will forget his password and try a few times before going to the “reset password” page. However, when a “user” keeps trying to authenticate with bad credentials, you may be subject to a brute-force attack. Therefore, you should collect failed authentication attempts. Your strategy may then be to block the account until further notice, while providing the user with a way to re-activate his account. When authentication fails, an event is fired, which you may intercept by registering an event listener or subscriber:
Symfony2: Security enhancements part I
When working with Symfony2, you already have many of the finest tools for securing your web application. There are cases however that require you to add that extra bit. In this post I will point you to the right extension points within a Symfony2 project (or any other project which uses the Security Component for that matter).
Install NelmioSecurityBundle
See the README of the NelmioSecurityBundle. It contains many add-ons for your project, to sign/encrypt cookies, force SSL, prevent clickjacking and prevent untrusted redirects.
Dependency injection smells
The Symfony2 DependencyInjection Component has made my life and work as a developer a lot easier. Choosing the right way to use it however can be a bit difficult sometimes. Knowing what a/the service container can do, helps a lot, and also thinking about how you would do it with just PHP can put you back on track. To be able to recognize some problems related to dependency injection in your own code, I will describe a few “dependency injection smells” below (a term derived from “code smells”, used by Kent Beck, Martin Fowler and the likes).
Symfony2 & Twig: Collecting data across templates using a node visitor
Writing PHP code with PHP is not very easy. You are constantly switching between the context of the code that generates the code and the code that is to be generated (see, you lost it already!). Some variables are available in the first context, some in the second, and you will have to pass the right values in the right way. One of the areas in Symfony-land where you will have to do these things is when you extend Twig by hooking into the parser and defining your own tags. A tag for example is the “for” in
Prevent controller execution with annotations and return a custom response
Symfony2 provides multiple ways of blocking, providing or modifying the response. You can:
-
Intercept each request by listening to the
kernel.request
event and set the response directly on the event (which will effectively skip execution of a controller) -
Modify the controller or its arguments by listening to the
kernel.controller
event, then callingsetController
on the event object and modifying the attributes of theRequest
object. -
Change the response rendered by a controller, by listening to the
kernel.response
event.
Symfony2: Application configuration for teams
A Symfony2 application provides developers with several ways to manipulate its behavior. First of all, it is possible to define different environments for different scenarios:
-
A “prod” environment to be used when the web application is on the live server
-
A “dev” environment used while developing the application. Generated parts of the application are regenerated when one of the files the generation was based on has changed
-
A “test” environment used when running functional unit tests/li>
Combining GridFS files with ORM entities
In my previous post I wrote about uploading files to GridFS. Therefor I created a MongoDB Document with a $file
property annotated with @MongoDB\File
. Because I am using ORM entities more often then ODM documents, I was looking for a seamless way to access a Document from an Entity.
Because it isn’t possible to define a direct relationship between an Entity and a Document I thought it would be a solid solution to create a custom field type. By defining a custom field type I can control the way the reference to the Document will be stored and at the same time I will be able to restore the reference when retrieving the field. The steps needed to create a custom field type for ORM entities are very similar to the post of Matthias on how to create custom field types for ODM documents.
Uploading files to MongoDB GridFS
Almost at the same time, I silently celebrate the first birthday of my blog. My first article appeared a little over a year ago. It is great to see how Symfony2 has become more and more popular during these twelve months. Your comments and visits encourage me to keep posting articles. So, thank you all! And thanks, Dennis, for contributing.
GridFS is a specification for storing large files in MongoDB. In this post I will explain how you can easily upload a file to GridFS and then retrieve it from the database to serve it to the browser.
Symfony2 & MongoDB ODM: Adding the missing ParamConverter
Just a quick post…
What seems to be missing from the DoctrineMongoDBBundle is a ParamConverter service which resolves request attributes to controller arguments by fetching a Document using the MongoDB DocumentManager. For entities, this would work:
/**
* @Route("/blog/{id}
*/
public function showAction(Post $post)
{
// $post will be the entity Post with the "id" taken from the route pattern
}
This works because of the DoctrineParamConverter, which is registered by default by the SensioFrameworkExtraBundle. But only for Doctrine ORM, and not for Doctrine MongoDB ODM. As Christophe Coevoet mentioned when someone tried to implement this missing feature, it can be added easily by yourself, without writing any PHP code, though it might not be so clear how to accomplish this. Still, the only thing you have to do is add a service to your services.xml
file:
Symfony2 & MongoDB ODM: Creating custom types with dependencies
With Doctrine MongoDB ODM it is possible to add custom field types and define how its values should be converted from and to the database. But type management in the MongoDB ODM currently suffers from several design flaws. This makes it non-trivial to create a custom type, especially when your type conversion has any dependencies. This is how it works:
use Doctrine\ODM\MongoDB\Mapping\Types\Type;
Type::registerType('custom', 'Matthias\CustomTypeBundle\MongoDB\Type\CustomType');
$type = Type::getType('custom');
// $type is an instance of Matthias\CustomTypeBundle\MongoDB\Type\CustomType
As you will understand, the Type
class is both a Registry and a Factory. Yet, it only allows you to define a type as a class, not as an object. This means: no constructor arguments can be passed. When using Symfony2, this implies that types can not be services, and you can use neither constructor nor setter injection.
Symfony2: Introduction to the Security Component part III
Authorization
When any of the authentication providers has verified the still unauthenticated token, an authenticated token will be returned. The authentication listener should set this token directly in the SecurityContext using its setToken() method.
From then on, the user is authenticated, i.e. means identified. Now, other parts of the application can use the token to decide whether or not the user may request a certain URI, or modify a certain object. This decision will be made by an instance of AccessDecisionManagerInterface.
Symfony2: Introduction to the Security Component part II
Authentication
When a request points to a secured area, and one of the listeners from the firewall map is able to extract the user’s credentials from the current Request object, it should create a token, containing these credentials. The next thing the listener should do is ask the authentication manager to validate the given token, and return an authenticated token when the supplied credentials were found to be valid. The listener should then store the authenticated token in the security context:
Symfony2: Introduction to the Security Component part I
The Security Context
Central to the Security Component is the security context, which is an instance of SecurityContext. When all steps in the process of authenticating the user have been taken successfully, the security context may be asked if the authenticated user has access to a certain action or resource of the application.
use Symfony\Component\Security\SecurityContext;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
$context = new SecurityContext();
// authenticate the user...
if (!$context->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
}
A firewall for HTTP requests
Authenticating a user is done by the firewall. An application may have multiple secured areas, so the firewall is configured using a map of these secured areas. For each of these areas, the map contains a request matcher and a collection of listeners. The request matcher gives the firewall the ability to find out if the current request points to a secured area. The listeners are then asked if the current request can be used to authenticate the user.
Symfony2 Security: Using advanced Request matchers to activate firewalls
In the Symfony2 security documentation both the firewalls and the access control rules are demonstrated using the “path” option, which is used to determine if a firewall or rule is applicable to the current URL. Also the “ip” option is demonstrated. The fact of the matter is, the string based configuration options in security.yml
are transformed into objects of class RequestMatcher. This is a curious class in the HttpFoundation component which allows you to match a given Request object. The Security component uses it to determine if it should activate a certain firewall for the current request (usually only by checking the request’s path info).
Symfony Security Component & Silex: Adding a security voter for domain names
The Symfony Security Component has an AccessDecisionManager which decides whether or not the currently authenticated user has a right to be in some place (or for that matter, use a certain service from the service container, or even call a certain method). The decision manager looks at the current user’s roles, and compares them to the attributes that are required. It relies on dedicated voters to make it’s verdict.
The component itself ships with an AuthenticatedVoter. It supports the “IS_AUTHENTICATED_FULLY”, “IS_AUTHENTICATED_REMEMBERED” and “IS_AUTHENTICATED_ANONYMOUSLY” attributes, which allow you to differentiate between users who are authenticated in the normal way, via a “remember me” cookie, or anonymously (which means: no credentials were supplied, but the user still gets a security context).
Symfony2 Security: Creating dynamic roles (using RoleInterface)
The Symfony Security Component provides a two-layer security system: first it authenticates a user, then is authorizes him for the current request. Authentication means “identify yourself”. Authorization means: “let’s see if you have the right to be here”.
The deciding authority in this case will be the AccessDecisionManager. It has a number of voters (which you may create yourself too). Each voter will be asked if the authenticated user has the right “roles” for the current URL.
Symfony2: Testing Your Controllers
Apparently not everyone agrees on how to unit test their Symfony2 controllers. Some treat controller code as the application’s “glue”: a controller does the real job of transforming a request to a response. Thus it should be tested by making a request and check the received response for the right contents. Others treat controller code just like any other code - which means that every path the interpreter may take, should be tested.
Symfony2 Config Component: Config Definition and Processing
My previous post was about finding and loading configuration files. I now continue my Symfony2 Config Component quest with a post about the way you can “semantically expose your configuration” (using the TreeBuilder). I wrote this piece to later contribute it to the Symfony documentation so feedback is very welcome!
Validate configuration values
After loading configuration values from all kinds of resources, the values and their structure can be validated using the Definition
part of the Symfony2 Config Component. Configuration values are usually expected to show some kind of hierarchy. Also, values should be of a certain type, be restricted in number or be one of a given set of values. For example, the following configuration (in Yaml) shows a clear hierarchy and some validation rules that should be applied to it (like: “the value for ‘auto_connect’ must be a boolean”):
Symfony2 Config Component: Using FileLocator, Loaders and LoaderResolver
The Symfony2 Config Component provides several classes to help you find, load, combine, autofill and validate configuration values of any kind, whatever their source may be (Yaml, XML, INI files, or for instance a database).
Locating resources
Loading the configuration normally starts with a search for resources - in most cases: files. This can be done with FileLocator:
use Symfony\Component\Config\FileLocator;
$configDirectories = array(__DIR__ . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'config');
$locator = new FileLocator($configDirectories);
$yamlUserFiles = $locator->locate('users.yml', null, false);
The locator receives a collection of locations where it should look for files. The first argument of locate()
is the name of the file to look for. The second argument may be the current path and when supplied, the locator will look in this directory first.
The third argument indicates whether or not the locator should return the first file it has found, or an array containing all matches.
Symfony2 & JMSSerializerBundle: Vendor MIME types and API versioning
The JMSSerializerBundle has a VersionExclusionStrategy
, which allows you to serialize/deserialize objects for a specific version of your API. You can mark the properties that are available for different versions using the @Since
and @Until
annotations:
use JMS\SerializerBundle\Annotation\Type;
use JMS\SerializerBundle\Annotation\Since;
use JMS\SerializerBundle\Annotation\Until;
class Comment
{
/**
* @Type("DateTime")
* @Since("1.2.0")
*/
private $createdAt;
/**
* @Type("DateTime")
* @Until("2.1.3")
*/
private $updatedAt;
}
The only thing you have to do is tell the serializer which version to use, before you start using it:
Symfony2: Setting up a Console-centered Application (with Composer)
I recently took a quick look at Composer and I have come to like it very much. I want to demonstrate the incredible ease of use. My example is also not trivial, it means to elaborate on the concept of a Console Application. The Symfony2 documentation does not tell us how to use the Console Component stand-alone, but only shows us how to add new commands to an already existing application. Therefore, let’s use Composer to set up a very light-weight Console Application, a good starting point from where you can add your own commands.
Symfony2 & Metadata: Caching Class- and PropertyMetadata
After creating a metadata factory and metadata drivers, we now need a way to cache the metadata, since collecting them at each request is way too inefficient. Luckily, the Metadata library provides us with a FileCache
(though it may be any kind of a cache, as long as it implements the same CacheInterface
). First, we make the FileCache
available as a service, and add a call to setCache
on the metadata factory:
<parameter key="matthias_annotation.metadata.cache_class">Metadata\Cache\FileCache</parameter>
<!-- ... -->
<service id="matthias_annotation.metadata.cache" class="%matthias_annotation.metadata.cache_class%" public="false">
<argument /><!-- the cache directory (to be set later) -->
</service>
<service id="matthias_annotation.metadata_factory" class="%matthias_annotation.metadata_factory.class%" public="false">
<argument type="service" id="matthias_annotation.driver_chain" />
<!-- call setCache with the new cache service: -->
<call method="setCache">
<argument type="service" id="matthias_annotation.metadata.cache" />
</call>
</service>
This provides the metadata factory with the file cache.
Symfony2: Writing a Yaml Driver for your Metadata Factory
In my previous post, I wrote about annotations and how to gather them using a metadata factory and an annotation driver. I also mentioned a future post in which I explain other ways of collecting metadata, namely by locating and parsing files in several different formats (distinguished by their extension). This is the post. In the case of our @DefaultValue
annotation, I’m thinking of a Yaml flavoured alternative. This allows us to store all default values as an array of property “name” - “value” pairs, like
Symfony2: Creating a Metadata Factory for Processing Custom Annotations
Earlier I wrote about how to create a custom annotation class. I used the annotation reader from Doctrine Common to check for the existence of the custom annotation inside the DocComment block. It is also possible to process the annotations on beforehand, and collect the processed data in ClassMetadata
and PropertyMetadata
objects. These objects are created by a MetadataFactory
. The factory uses Drivers
to collect the metadata.
My purpose in this article is to create a custom annotation @DefaultValue
which allows me to define default values for properties of a class. It should work like this:
Symfony2: creating a ParamConverter for deserializing request content
In my previous post I wrote about a listener that deserializes the request content and replaces controller arguments with the result. Johannes Schmitt made the suggestion to use a ParamConverter
for this. This of course makes sense: currently there is only a ParamConverter
for converting some “id” argument into an entity with the same id (see the documentation for @ParamConverter.
In this post I will show you how to create your own ParamConverter
and how we can specialize it in deserializing request content.
Symfony2: Deserializing request content right into controller arguments
Based on the list of most popular search results leading to my blog, using Symfony2 for building some kind of webservice seems to be quite “hot”. It also seems many people are struggling with the question how they should serialize their content to and from XML and/or JSON. Two beautiful bundles are already available for this, FOSRestBundle and JMSSerializerBundle. Both will help you a lot with this issue, by providing transparent conversion between formats for both the request content and the response body. Nevertheless, a few things are missing. For example, I want to really serialize and deserialize objects, for example, when I send a request with a comment (or part of it) like this:
Wordpress & Symfony2: using the CssSelector and FluentDOM to filter HTML snippets
Recently I created my first WordPress template (the one you are looking at right now) and I was left both in shock and in great awe. This piece of software written in PHP has many users (like myself), yet it is so very outdated. The filtering mechanism by which you can modify HTML after it is generated by WordPress feels very dirty. But because a lot of the HTML snippets that WordPress generates are not suitable for decorating with Twitter Bootstrap’s beautiful CSS rules, I used those dirty filters extensively.
The Symfony2 Serializer Component: create a Normalizer for JSON class hinting
I was looking for a way to serialize domain objects into JSON strings and back again into objects of the original class. This is essential for webservices, especially those built around the JSON-RPC specification that allow clients to make calls to their server and, for example add new personal data to their database of contacts. It makes life a lot easier when this data matches the field names and inner structure of your own domain objects. For example, a JSON string like {"name":"Matthias Noback"}
should be easily translatable to an object of class Acme\Webservice\Entity\Person
with a private property name. But how do you know which class to instantiate, when you only have the simple JSON string above?
Symfony2: dynamically add routes
Earlier I was looking for an alternative to Symfony1’s routing.load_configuration
event, so I could add some extra routes on-the-fly. This may be useful, when routes change in more ways than only variable request parameters as part of routes do (you know, like /blog/{id}
). I got it completely wrong in my previous post about this subject. Of course, adding extra routes is a matter of creating a custom routing loader, and tell the framework about it using the service container. So, there we go.
Symfony2: Extending forms globally ("you know, like with CSRF protection")
With Symfony2, many things are managed through dependency injection. Except for forms. Oh, wait, forms can be services too of course! Remember? Any class instance can be a service… Now, as in many other cases, Symfony2’s FrameworkBundle
adds some magic to the Form component by creating services that link several parts of the Form component together. For example, depending on the value of the framework.csrf_protection
parameter in config.yml
file a hidden field “_token” will be added to all forms, site-wide. To create this kind of very general “form extension” in your own project, you need to do just a few things (I am going to use the example of a “Captcha” form extension, but I don’t give a full implementation of this idea).
Symfony2: Creating a Validator with dependencies? Make it a service!
One of the ugly things about Symfony 1 validators was that their dependencies were generally fetched from far away, mainly by calling sfContext::getInstance()
. With Symfony2 and it’s service container, this isn’t necessary anymore. Validators can be services. The example below is quite simple, but given you can inject anything you want, you can make it quite complicated. I show you how to create a validator that checks with the router of the value-under-validation is a route.
Symfony2: An alternative to Symfony 1's "routing.load_configuration" event
Symfony 1 had the lovely routing.load_configuration
event. Listening to this event enabled the developer to add some routes dynamically, “on-the-fly”. Plugins used to do this most of the time. I was looking for a way to accomplish the same in Symfony 2. I’ve used the following as a solution.
We are going to listen to the kernel.request
event, but we make sure we get notified in an early stage, so that the router hasn’t done it’s magic yet. Then we quickly add some extra routes to the RouteCollection
.
Symfony2: running PHPUnit from within a controller
When you don’t have access to the command-line of your webserver, it may be nice to still run all your unit tests; so you need a way to execute the phpunit
command from within a controller. This way, you can call your test suite by browsing to a URL of your site. To do things right, we start with a “test” controller /web/app_test.php
containing these lines of code:
if (!in_array(@$_SERVER['REMOTE_ADDR'], array(
'127.0.0.1',
'::1',
))) {
header('HTTP/1.0 403 Forbidden');
exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
}
require_once __DIR__.'/../app/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';
use Symfony\Component\HttpFoundation\Request;
$kernel = new AppKernel('test', true);
$kernel->loadClassCache();
$kernel->handle(Request::createFromGlobals())->send();
In fact, just copy everything from /web/app_dev.php
but replace the string “dev” by “test”.
Symfony2: define your bundle's configuration values using the TreeBuilder
After reading the Cookbook article How to expose a Semantic Configuration for a Bundle I became interested in the possibilities for defining a configuration tree using the TreeBuilder
from the Symfony component Config
. This
TreeBuilderallows you to build a schema against which the configuration values (or short: config) from
/app/config.yml` and the like are to be validated.
Create an Extension
First make sure that your bundle has a /DependencyInjection/[BundleNameWithoutBundle]Extension.php
containing the extension class:
Symfony2: use a bootstrap file for your PHPUnit tests and run some console commands
One of the beautiful things about PHPUnit is the way it can be easily configured: for example you can alter the paths in which PHPUnit
will look for TestCase
classes. In your Symfony2 project this can be done in the file /app/phpunit.xml
(if it is called phpunit.xml.dist
, rename it to phpunit.xml
first!). This file contains a default configuration which suffices in most situations, but in case your TestCase classes are housed somewhere else than in your *Bundle/Test
, add an extra “directory” to the “testsuite” element in phpunit.xml
:
Symfony2: how to create a custom Response using an event listener
In some cases you want to return a very specific Response
in case the Request
has some properties like a certain response format.
This situation calls for an event listener, which listens to the kernel.request
event. The listener itself should be a service with some special characteristics: it has the tag “kernel.event_listener” and some extra attributes, i.e. the name of the event
to which it listens and the method
of the service that should be called when this event occurs. When you want to return a very specific Response
, you should listen to the kernel.request
event. We want the kernel to call the method onKernelRequest()
, which we will define later.
Use DocBlox in Symfony2 for inspecting DocComment blocks
I was looking for a way to automatically generate some documentation, and because all the required information was already in the DocComment
blocks. I downloaded the great documentation generator DocBlox (which is a PHP application by itself) and looked in it’s source code. Soon I found DocBlox’s Reflection
classes which are able to parse a DocComment
block. So I wanted to use these classes! Here is how you can do it:
Symfony2: create a response filter and set extra response headers
Sometimes you need to make changes to the Response object, after it is returned by your controller, but before it is rendered as output to the client (e.g. the browser). You may want to set some extra response headers, or “completely mess up the content” of the response. You can accomplish this by creating an event listener that listens to the kernel.response
event. I give you a sample event listener which changes the Content-Type
header in case the requested format is “json” and the browser’s accepted response format contains “text/html”; in that case, at least in my experience, the browser doesn’t render the JSON string as plain text when the status code is 4xx or 5xx. So in these situations, the event listener changes the “Content-Type” to “text/plain”, to be sure you always get decent output in the browser.
Symfony2: How to create a UserProvider
Symfony2 firewalls depend for their authentication on UserProviders
. These providers are requested by the authentication layer to provide a User
object, for a given username. Symfony will check whether the password of this User
is correct (i.e. verify it’s password) and will then generate a security token, so the user may stay authenticated during the current session. Out of the box, Symfony has a “in_memory” user provider and an “entity” user provider. In this post I’ll show you how to create your own UserProvider
. The UserProvider
in this example, tries to load a Yaml file containing information about users in the following format:
Symfony2 service container: how to make your service use tags
First of all: dependency injection is GREAT!
Several of Symfony2’s core services depend on tags to recognize which user-defined services should be loaded, notified of events, etc. For example, Twig uses the tag twig.extension
to load extra extensions.
It would also be great to use tags in case your service implements some kind of “chain”, in which several alternative strategies are tried until one of them is successful. In this post I use the example of a so-called “TransportChain”. This chain consists of a set of classes which implement the Swift_Transport
interface. Using the chain, the mailer may try several ways of transport, until one succeeds. This post focuses on the “dependency injection” part of the story. The implementation of the real TransportChain
is left to the reader (as an exercise ;)).
Dutch PHP Conference wisdom applied to working with the symfony framework
Last week I was one of the several hundreds of PHP developers who traveled “all te way” to Amsterdam for the Dutch PHP Conference 2010. Though I had the impression that many PHP developers are using the symfony framework for their web applications, the speakers at this conference were friendlier towards the “father of the framework”, Fabien Potencier, than towards the framework itself. Fabien is a much admired developer himself, who is very conscious about software architecture, latest trends in PHP development and also is aware of the importance of fully covering the framework’s code with unit tests. In this article I will try to apply to the symfony framework, several comments on PHP programming and frameworks that I heard during this conference.