I’ve been using more and more Value Objects in my applications over the last year, primarily with Doctrine ORM. Value Objects are an extremely powerful technique and I’ve been impressed with how much they can clean up a codebase.

One of the main questions I’ve had when starting with Value Objects is how to persist them with Doctrine. This post attempts to create a reference for all the different persistence techniques I’ve seen so far. Keep in mind, I’ll be talking purely about persistence, not about how to use Value Objects as part of your modeling. I’ll also assume that you’re somewhat familiar with the concept of a Value Object and a fair hand with Doctrine. If not, I’d suggest reading up on both topics before going further.

It’s important to understand that (until recently) Doctrine had no true support for Value Objects and therefore almost all of the techniques you’ll see are workarounds, so keep that in mind.

Map It Yourself

Let’s say you wanted to store IP ranges in your database. We’ll start off simple, storing ranges as strings in CIDR notation like “192.168.1.1/24” (don’t worry if that doesn’t make sense, it’s just a shorthand for expressing 192.168.1.1 – 192.168.1.255). We’ll use a couple of Value Objects like this:

class IPAddress
{
    public function createFromString($ipAsString);
    public function __toString();
}

class IPRange
{
    // Returns the high or low IP addresses of this range.
    public function getStartIP();
    public function getEndIP();

    // Different ways of creating this value object
    public static function createFromCidrNotation($cidr);
    public static function createFromIPAddresses(IPAddress $startIP, IPAddress $endIP);

    // Cast the range to a CIDR notation
    public function __toString();
}

Now, let’s imagine we have a Server entity that’s responsible for storing an IPRange:

class Server
{
    public function setIPRange(IPRange $range);
    public function getIPRange();
}

So, we have an Entity (Server) that stores a Value Object (IPRange) that is made out of two other value objects (IP Address) and this all needs to be stored. This is more complicated than a standard Entity->Value Object but it lets us explore more trade offs.

The important thing is the interface on the entity itself: it only deals in Value Objects. What happens inside the entity is technically the entity’s business. We only really care that an IPRange is given and returned, not what form it takes inside the entity.

With that in mind, the simplest way to handle a value object in Doctrine is to just map it to and from the database format yourself, in the entity code.

/**
 * @Column(type=”string”)
 */
protected $ipRangeAsCidr;

public function setIPRange(IPRange $range) {
    $this-> ipRangeAsCidr = $range->__toString();
}

public function getIPRange() {
    return IPRange::createFromCidrNotation($this->ipRangeAsCidr);
}

The example above might seem a bit dumb but that’s all internal to the entity. To the rest of the world, the integration is flawless and that’s what’s really important. Yes, we are mixing concerns. Yes, that makes a single tear roll down my cheek. Nonetheless, on the Grand Scale Of Architectural Sins, this is probably a lesser.

However, before you grit your teeth and bear it, keep in mind that for 80% of your use cases, a better way already exists.

DBAL Types

For most Value Objects, a custom DBAL type is the best option today. If you’re not familiar with a DBAL Type, imagine the DateTime mapping. When I set a property as a DateTime in Doctrine, it appears in PHP as a Datetime object but it’s stored in the database in the famous ‘Y-m-d H:i:s’ format. Something has to do this conversion. That’s what the DBAL types are for.

These are small converter objects with a super simple interface:

convertToDatabaseValue($value, AbstractPlatform $platform)
convertToPHPValue($value, AbstractPlatform $platform)

where $value is the PHP or raw database value and $platform represents the type of database you’re working with (MySQL, Postgres, etc). The $platform is extremely useful if the column type might vary based on the database (for example, Postgres has a native IP Address type but we might fallback to a string or integer in MySQL).

If your value is going to be represented as a single column in the database, DBAL types are by far the best solution. They’re easy to build and Doctrine supports them as a core feature. Furthermore, you can override getSqlDeclaration() to add support for Doctrine migrations or custom declarations.

public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
    // Built-in helper function for getting platform independent DDL
    return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration);
}

For more details, check the docs. http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html#custom-mapping-types

Multiple Columns

Unfortunately, DBAL types are limited: They only work if you have a single value and you want to store it in one column. So, if my database looked like this…

|---------------|
| ip_range      |
|---------------|
| 192.68.1.1/24 |
| 4.2.2.1/24    |
|---------------|

…DBAL types would be fine. If I wanted them to look like this…

|------------+---------------|
| start_ip   | end_ip        |
|------------|---------------|
| 192.68.1.1 | 192.168.1.254 |
| 4.2.2.1    | 4.2.2.254     |
|------------|---------------|

…then I’m out of luck.

In the current stable release of Doctrine, falling back to the “Map It Yourself” method is your best bet.

/**
 * @ORM\Column(type=”ip_address”)
 */
protected $startIP;

/**
 * @ORM\Column(type=”ip_address”)
 */
protected $endIP;

public function setIPRange(IPRange $ipRange)
{
    $this->startIP = $ipRange->getStartIP();
    $this->endIP = $ipRange->getEndIP();
}

public function getIPRange()
{
    return new IPRange($this->startIP, $this->endIP);
}

In the example above, we’re splitting this into two properties/columns internally but holding to the external contract. Keep in mind that the startIP() and endIP() methods return IPAddress Value Objects (rather than IPRange). This means we’re still using our IPAddress DBAL type for its standard string handling, etc (otherwise, you would also need to cast each $ipAddress to and from a string representation like in the Map It Yourself technique).

If you’re using the value object elsewhere inside your object and don’t want to constantly recreate it, you might consider a third unmapped property with the value object and only using the other two mapped properties for database reading/writing. This is useful, even when using the Map It Yourself technique.

// No annotations, thus not saved in the db.
protected $ipRange;

/**
 * @ORM\Column(type=”ip_address”)
 */
protected $startIP;

In the event of multiple properties shared across multiple classes, you could potentially use a trait to avoid repeating this code everywhere.

If you read the above, you might be thinking “Why should I bother with DBAL types at all if I’m just going to map everything myself eventually?” Remember, in most cases, you’ll only have the one value and the DBAL Type will suffice.

So, this method is reasonably simple but we’re still mixing concerns and repeating this across entities will create duplicate code.

Don’t fear, help is on the way.

Embeddables, The Promised Land

A better method for managing Value Objects has been a long running Doctrine pull request (the original JIRA ticket dates back to 2009 ). Several years and PRs later, it’s only one release away.

This new feature, called Embeddables, allows one to embed a non-entity class inside an entity. The feature is aimed at storing Value Objects but uses the more generic name “Embeddable” to be more inclusive towards other use cases.

I haven’t personally used this feature but the early docs are already online.

Based on the PR, however, we should be able to get the best of both worlds: Reusable mappings/types AND flattened database columns. I suspect a solution would look like this:

<?php

/**
 * @Embeddable
 */
class IPRange
{

    /**
     * @Column(type="ip_address")
     */
    protected $startIP;

    /**
     * @Column(type="ip_address")
     */
    protected $endIP;

    // public methods...
}

// And then in our entity...

class Server
{
    /**
     * @Embedded(class="IPRange")
     */
    protected $ipRange;
}

In this example, our Server entity has an embedded IPRange object. Notice that we’re using a different annotation, @Embedded, rather than an @Column type. That’s because @Column(type=*) maps to DBAL types but @Embedded maps to a regular PHP object with Doctrine metadata.

The IPRange itself is still using the ip_address DBAL type we created before because of a major limitation with Embeddables: you can’t use them inside of other Embeddables. (Update: No longer true, this was fixed by Doctrine 2.5! Hooray!) That might sound like overkill but it would’ve been perfect for our use case: we could’ve had the Server containg an Embeddable for the IPRange and the IPRange could’ve had 2 Embeddables for the start and end IP Addresses. (Update: And now that it’s there in 2.5, it’s exactly what I’d do! Hooray!)

Still, embeddables are simpler than creating lots of DBAL types: you’re just using adding Doctrine metadata to PHP objects like you normally do.

Even better, the Value Object fields are split into actual database columns so you can query them easily. The default naming strategy is the entity property name and the embeddable property name, combined with an underscore. In our case:

|-------------------+-----------------|
| ip_range_start_ip | ip_range_end_ip |
|-------------------|-----------------|
| 192.68.1.1        | 192.168.1.254   |
| 4.2.2.1           | 4.2.2.254       |
|-------------------|-----------------|

Embeddables are now in Doctrine master and are slated to be released with 2.5 to much fanfare and acclaim. Once they’re released, these should replace DBAL types as your default method for dealing with Value Objects.

Multiple Value Objects (i.e. Collections)

So far, we’ve talked about single values as one or more columns, but what about when you have multiple columns? For example, a record might have multiple IPRanges it should check for.

Unfortunately, neither DBAL types nor Embeddables work in these situations. They have no support for collections. Filthy as it is, I usually recommend a Fake Entity. Simply put, you create a fake entity that does nothing but contain your value object. This way, you can use Doctrine’s *ToMany relations on the fake entity and thus your value object.

The important rule here is to not expose these fake entities outside your object. If you have a list of IPRanges and those are encapsulated in IPRangeAssignments fake entities, then a getter should loop over and expose only the IPRanges, as these are the contract you want.

/**
 * @Entity
 */
class IPRangeAssignment
{
    /**
     * @Embeddable/@Column/@Whatever method of storing the IPRange
     */
    protected $ipRange;
}

/**
 * @Entity
 */
class Server
{

    /**
     * @OneToMany(targetEntity="IPRangeAssignment", orphanRemoval=true)
     */
    protected $ipRangeAssignments;

    public function __construct()
    {
        $this->ipRangeAssignments = new ArrayCollection();
    }

    public function setIpRanges(Collection $ipRanges)
    {
        // Converts a list of IPRange objects to IPRangeAssignment
        $this->ipRangeAssignments = $ipRanges->map(function($ipRange) {
            return new IPRangeAssignment($ipRange);
        });
    }

    public function getIPRanges()
    {
        // Unwrap the IPRangeAssignments back to IPRanges
        return $this->ipRangeAssignments->map(function($ipRangeAssignment) {
            return $ipRangeAssignment->getIpRange();
        });
    }
}

This method’s noise and boilerplate makes it less than pleasing but it works fairly well. You can clean this up by using custom helper collections or even a trait to reuse the code across multiple classes.

However, after some experience with it, I’ve come to regard it as a design smell. When clients want lists of Value Objects, they often later want to add metadata, such as priorities, dates or names. This is logical for the end user since Value Objects have no identity of their own.

Thus, the IPRangeAssignment may quickly go from fake entity to actual entity once you add the metadata. It would be best to avoid the work of breaking the contract and ask your client more up front.

Other Avenues (that I tend to avoid)

I’d be remiss if I didn’t talk about serialization. The quickest, easiest way to store a Value Object or collection in Doctrine is to just serialize it into a single column. You can do this with Doctrine’s built in serialization support (these are just DBAL types), json_encode it or just call serialize yourself. Again, as long as you keep this internal to the model, it’s not a massive issue.

The drawback is that you can’t effectively query this data. Technical debt isn’t just something that appears in your code. Your infrastructure, your processes, and yes, your database can all have technical debt. Simplifying your code at the expense of complicating your database is just moving the debt around.

So, I might serialize values into my database when I’m absolutely 100% sure that I’ll never want to run queries over them or change the data from anything other than my application. In all other cases, I prefer to spend the extra few minutes setting up a DBAL type, Embeddable or Fake Entity.

Another option would be to use Doctrine’s Event system to do the mapping yourself but external to the class. I’m a big fan of events but they’re probably not the best fit here: it’s more complex than the other options and you may still need to expose the internal state of your object to set things back inside it. If I wanted to make updates to other Entities, I might use the Event system but I’d be more likely to use a Domain Event than a Doctrine Event.

The Nuclear Option

Finally, Doctrine is great for the vast majority of applications but if you’ve got edge cases that are making your entity code messy, don’t be afraid to toss Doctrine out. Setup an interfaces for your repositories so create an alternate implementation where you do the querying or mapping by hand. It might be a PITA but it might also be less frustration in the long run.

You can also do this in a partially, by letting Doctrine map the simple properties of your entity and then use the postLoad event to attach some complex object building at hydration time.

Finally, don’t lose sight of the real goal here: using Value Objects in your code. Don’t let this article scare you off with the complexity for some of the more extreme solutions; Value Objects can improve your codebase tremendously and they’re a solution worth investing in.

*Many thanks to Marco Pivetta, Rafael Dohms, Sandy Pleyte and Benjamin Eberlei for suggestions and corrections related to this article.

In case you haven’t seen it, I’m writing a 3-part series about HTTP ETags on the Ibuildings blog. The first two parts have already been published and the third will be out early next year. The literature for using ETags in practice is a bit scattered so I hope this will help centralize it.

If you prefer video, most of the content is covered in my HTTP & Your Angry Dog talk, recorded earlier this year at LaraconEU.

Some recent converations prompted me to gather some of my recent Raphael related links in one place.

  • For starters, my introductory article to Raphael “Pretty, Pretty Pictures” was published in this month's PHPArchitect.

  • For a more in-depth look, NEPHP recorded my presentation on the subject “Team Plaatjes” earlier this year.

  • Or just checkout the slides online. (Tested in Chrome)

  • If you’d like to do 2D graphics in the browser and don’t need to support older browsers, take a look at Adobe’s opensource SnapSVG library, created by Raphael’s creator Dmitry Baranovskiy.

Note

This post is outdated (2009). Specifically, the Callable typehint and Closure typehints should be preferred to is_callable && is_object. You can also use $this inside anonymous functions from 5.4 as well.

One of the things I’ve been really looking forward to in PHP 5.3 is seeing what I could do with closures. There’s some handy obvious use cases (strategy object substitutes, for instance) but I’m interested in some more dynamic things so I grabbed a fresh set of packages from DotDeb and started hitting closures with the reflection API.

I’m pleased to report that things Just Work(tm). Couple of examples below:

$func = function($one, $two = 'test') {
    echo 'test function ran'.PHP_EOL;
};
$info = new ReflectionFunction($func);
var_dump(
    $info->getName(), 
    $info->getNumberOfParameters(), 
    $info->getNumberOfRequiredParameters()
);

Which returns:

string(9) "{closure}"
int(2)
int(1)

I’m glad it’s there, but the closure’s trailing semicolon still tastes a bit weird. Anyways, couple of interesting things here. First off, the function reflection API seems to work. No surprise, but a relief nonetheless.

Secondly, if you look at the returned name for a closure it’s always “{closure}”. This remains the same irregardless of how many closures you currently have in scope. The PHP C source code doesn’t seem to be setting the name to a constant anywhere* so I wouldn’t rely on this as a method to detect closures since it may be subject to change. The manual also states that while closures are implemented using the closure class, that’s not a reliable way to detect a closure either. This leads to the question of what IS the recommended method of detecting a closure. To be honest, I have no idea. The docs are still mum on this issue, there doesn’t seem to be any is_function/lambda/closure function in the new library and I can’t find any examples. Luckily, is_callable() does work so you can do some validity checking but that doesn’t differentiate between the string or array callback types. Little weird, but I’m hoping there’ll be something more about this soon. EDIT: The best solution I’ve found so far is (is_callable($func) && is_object($func)).

Okay, let’s try a more blinged out example:

$name = 'Ross';
$func2 = function($one, $two = 'test') use ($name) {
    return true;
};
 
$info2 = new ReflectionFunction($func2);
var_dump($info2, 
    $info2->getParameters(),
    $info2->getName(),
    $info2->isInternal(),
    $info2->isDisabled(),
    $info2->getFileName(),
    $info2->getStartLine(),
    $info2->getEndline(),
    $info2->returnsReference(),
    $info2->getDocComment()
);

which returns

//getParameters()
object(ReflectionFunction)#2 (1) {
  ["name"]=>
  string(9) "{closure}"
}
array(2) {
  [0]=>
  &object(ReflectionParameter)#3 (1) {
    ["name"]=>
    string(3) "one"
  }
  [1]=>
  &object(ReflectionParameter)#4 (1) {
    ["name"]=>
    string(3) "two"
  }
}
string(9) "{closure}"   //getName()
bool(false)             //isInternal()
bool(false)             //isDisabled()
string(32) "/path/closure.php" //getFileName()
int(72)                 //getStartLine()
int(74)                 //getEndline()
bool(false)             //returnsReference()
string(27) "/**         //getDocComment()
 * Docblock Comment
 */"

Most of that speaks for itself. It’s cool that docblock reflection works, especially with some of the docblock DSL work going on (as seen in the Doctrine 2.0 teaser, for example). Also, in case it’s not immediately obvious, you can return a reference from a closure, you just need to put the ampersand between the parantheses and the function keyword (whitespace isn’t required, you can just use “function&($etc)”.

The reflection parameters work fine except that I can’t seem to reflect on anything handed in through the “use” clause. That’s a bit of a shame, but considering that you can’t really manipulate the variables imported, it doesn’t really matter. The important thing is that we can reflect on the arguments (and their type hints) which paves the way for closure dependency injection and other outright tomfoolery.

Moving on to classes, let’s try assigning a closure directly to a property.

class ClassName {
    public $test = function($test) { echo 'test'; };
}

Unfortunately, that returns an error:

PHP Parse error:  syntax error, unexpected T_FUNCTION in

I’m admittedly a bit disappointed here, I was really hoping this would work.

There’s a good IBM Developer Works article on some of this, but some of the things shown in the examples no longer work for me. For instance, the following example:

class ClassName {
    public function __construct() {
        $this->test = function($arg) { 
            return function () { echo 'grr'; };
        };
    }
}
 
$c = new ClassName();
$c->test();*/
 
class Dog
{
    private $_name;
    protected $_color;
 
    public function __construct($name, $color)
    {
         $this->_name = $name;
         $this->_color = $color;
    }
 
    public function greet($greeting)
    {
         return function() use ($greeting) {
             echo "$greeting, I am a {$this->_color} dog named {$this->_name}.";
         };
    }
}
 
$dog = new Dog("Rover","red");
$dog->greet("Hello");

When the IBM article was written the returned closure would have been executed, displaying the cute dog message. Unfortunately, this was cut before 5.3.0 final was out and the function now only returns the closure. The changes seem to be summarized in the rfc:closures:removal-of-this which basically says you can’t use $this inside a closure which makes some sense. Keep an eye out when returning closures because if you accidentally use $this the error won’t spring up until the function is executed which could be a long ways away by then; it’s not a big deal though since the error message gives the original line holding $this. The RFC also says a few other goodies were hauled out then as well like “static” and the fascinatingly odd getClosure() method which would’ve returned an object method as a closure.

The returned closure, by the way looks like this when var_dump’ed:

object(Closure)#2 (1) {
  ["static"]=>
  array(1) {
    ["greeting"]=>
    string(5) "Hello"
  }
}

Neat, it keeps holding the imported variables. I wonder…

$func = $dog->greet("Hello");
$info = new ReflectionClass($func);
var_dump($info->getProperties());

Nope.

array(0) {
}

Oh well. ;)