Symfony World blog is not maintained anymore. Check new sys.exit() programming blog.

symfony & Doctrine behavior review

Doctrine behaviors

The main idea of this article is to create a short summary on Doctrine behaviors (really powerful and useful tools) which speed up development significantly. I tried to mention the most important behaviors, providing brief description and links. It's quite common to reinvent the wheel, being just unconscious that someone has already implemented a feature you are just in need of. Moreover, I hope that both beginners and advanced symfony developers will find this article a useful source of brief information about Doctrine behaviors for everyday use.

Basically, a behavior lets you share some relations, algorithms and other features among your project's model. They are (or at least should be) highly configurable: providing you a mechanism that can be easily customized to fit in different projects. Customization usually includes: enabling/disabling some of the behavior features (you may use only some of them), renaming additional schema columns, configuring them (like adding 'not null'), etc. You can use many Doctrine behaviors in your projects: core behaviors, Doctrine extensions, symfony plugins - or if you've got nothing better to do late at nights - you can create your own behaviors ;)

Core behaviors

The Doctrine ORM is bundled with several behaviors (calles core behaviors), these are:

  • Versionable - add an entire XxxVersion table to store your Xxx model object versions as either only version numbers or numbers versions along with ALL column data - to see object data changes through time,
  • Timestampable - probably the most popular of all behaviors, adds created_at and updated_at timestamp columns to your model, automatically saving datetime when a record is created or updated, respecticely,
  • Sluggable - adds a slug column that stores a slug which is a unique index automatically and can be used along with sfDoctrineRoute class to refer to an object without passing its ID as a parameter; by default the update is disabled, since this may harm your search engines rating,
  • I18n - add an entire XxxTranslation table to provide Internationalization (I18n) for your Xxx model, essential when developing a multi-language project,
  • NestedSet - adds root_id, lft, rgt and level columns to your model to develop an advanced hierarchical data structure (such as product categories), nested sets is an alternative to adjacency model, more details on hierarchical data here,
  • Searchable - choose model columns you want to index and add an entire database table, speeding up a basic search engine development, more info about searching here,
  • Geographical - adds longitude and latitude columns storing geographical coordinates. Ever needed to use gmaps in your project, along with sfEasyGMapPlugin? Not only this behavior suits the data structure you need, but also provides you with getDistance() method to calculate distance between two Geographical objects,
  • SoftDelete - adds a deleted_at column which defines if a record has been marked as deleted (and if so, when). Useful when designing a highly complicated system where data consistency is important and even if some data should be invisible in the backend, it should still remain in the database.

extension behaviors

You may also use Doctrine extensions:

  • Blameable - adds an additional level of auditing capabilities to models, blameable allows you to track who created or last updated any model in an environment with many users, blameable is a great companion to Timestampable behavior,
  • EventLoggable, readme - logs any Doctrine Events (pre/post Delete/Insert/...) fired upon a record, log type may be chosen (e.g. file) and events may be limited to the chosen ones only,
  • Localizable - gives you functionality to convert units of measurement (e.g. kilometers to miles, etc.) or any other conversions desirable,
  • Locatable - gives you functionality using the Google Maps API to automatically populate your model with latitude and longitide information using Google, a fantastic tool to use along with sfEasyGMapPlugin,
  • Sortable - gives you sortable functionality to your models, enabling you to easily fetch next/previous objects, moving them up/down in a sorted list or swapping with another object,
  • Taggable - adds Tagging capabilities, creates a TaggableTag table and a XxxTaggableTag table for each taggable model, using refClass m:n db table relation, provides easy tag management: add, remove, remove all, set, etc, finally, gives you the possibility to get the most popular tags (for a tag cloud, for example) fetched either from chosen models or from all of them,

plugin behaviors

Finally, there are also symfony plugins providing custom behaviors:

useful links about Doctrine behaviors:


If you find any information missing, please, let me know. Hopefully, you'll find it useful, otherwise I'll lose the motivation to do such thing next time ;)


  1. Hi,
    Just to say there is also a Commentable behavior in my plugin (and in others) vjCommentPlugin.
    This plugin make a lot of stuff but including the behavior.

  2. I've yesterday released a plugin adding fulltext search support to the admin generator for doctrine, also using a behaviour: ajDoctrineLucenablePlugin. Let me know what you think.

  3. Just wanted to drop in a very, very heartfelt thank you for your post! You are AWESOME!

    I will be working with Symfony soon and decrypting the various mystifying options available for use in schema.yml was making me cross-eyed. Been searching for hours before stumbling across this post.

    Though Symfony and Doctrine are very well documented, looking for Behaviours and/or "actAs" does not readily provide you with a link to the "Core Behaviours" you've talked about here...

    So THANK YOU!!!

    Tweeted this :o)

  4. Sooooo I've now created 3 different ways to timestamp my entities, and I just now run across this.

    Ugh, thanks for showing me how much time I wasted!

    1. Well, UR welcome ;) but it's a pity you didn't come across this article before you implemented your solutions ;-)