I have been implementing value objects as custom DBAL types in Doctrine 2 and it's been working OK. However I have been wondering if this is the best way. I've thought about using the Post Load listener to instantiate the Value Objects. Also instantiating them through Entity accessors when requested, the advantage with the latter would be that I would not instantiate more objects than I need.
My question is: which method is best? Or is there a better way to do it? Are there any gotchas or unreasonable performance hits with the above?
As an example, the Doctrine Mapping Type string defines the mapping from a PHP string to a SQL VARCHAR (or VARCHAR2 etc. depending on the RDBMS brand). Here is a quick overview of the built-in mapping types: string : Type that maps a SQL VARCHAR to a PHP string. integer : Type that maps a SQL INT to a PHP integer.
A repository in a term used by many ORMs (Object Relational Mappers), doctrine is just one of these. It means the place where our data can be accessed from, a repository of data. This is to distinguish it from a database as a repository does not care how its data is stored.
The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share. You can use these interfaces and abstract classes to build your own mapper if you don't want to use the full data mappers provided by Doctrine.
IMHO, both approaches are equally valuable, while waiting for native support for value objects.
I personally favor the second approach (instantiating them through accessors when requested) for two reasons:
An example of this approach:
class User
{
protected $street;
protected $city;
protected $country;
public function setAddress(Address $address)
{
$this->street = $address->getStreet();
$this->city = $address->getCity();
$this->country = $address->getCountry();
}
public function getAddress()
{
return new Address(
$this->street,
$this->city,
$this->country
);
}
}
This code will be fairly easy to refactor when Doctrine will offer native VO support.
About custom mapping types, I do use them as well, for single-field VO (Decimal
, Point
, Polygon
, ...) but would tend to reserve them for general-purpose, reusable types that can be used across multiple projects, not for project-specific single-field VO where I would favor the approach above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With