Below you will find pages that utilize the taxonomy term “Annotations”
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.
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 & 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 & 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 & 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:
Symfony2 & Doctrine Common: creating powerful annotations
I was looking into the Doctrine Common library; it seems to me that especially the AnnotationReader
is quite interesting. Several Symfony2 bundles use annotation for quick configuration. For example adding an @Route
annotation to your actions allows you to add them “automatically” to the route collection. The bundles that leverage the possibilities of annotation all use the Doctrine Common AnnotationReader (in fact, the cached version) for retrieving all the annotations from your classes and methods. The annotation reader works like this: it looks for annotations, for which it tries to instantiate a class. This may be a class made available by adding a use
statement to your file. That is why you have to add use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route
to any PHP file in which you use the @Route
annotation.