January 15, 2010 – 14:47
My latest Symfony project uses Doctrine as ORM, which is considered to be a lot better than Propel by many people…
Well, not by me. Doctrine seems to have a couple of very good concepts, amongst them built-in validators, a powerful query language, and last but not least, an easy schema language. (Though to be fair, Propel will gain most of these useful things in the future as well or already has, f.e. with its PropelQuery feature.)
But Doctrine also fails in many areas; the massive use of overloads everywhere makes it very hard to debug and even worse, it tries to outsmart you (the developer) in many areas, which makes it even more hard to debug stuff which Doctrine doesn’t get right.
A simple example – consider this schema:
Foo:
columns:
id: { type: integer(5), primary: true, autoincrement: true }
name: { type: string }
Bar:
columns:
id: { type: integer(5), primary: true, autoincrement: true }
name: { type: string }
FooBarBaz:
columns:
foo_id: { type: integer(5), primary: true }
bar_id: { type: integer(5), primary: true }
name: { type: string }
(I’ll skip the relation setup here, Doctrine should find them all with an additional detect_relations: true)
So what do you expect you see when you call this?
$obj = new FooBarBaz();
print_r($obj->toArray());
Well, I expected to get an empty object, with a NULLed foo_id and bar_id, but I didn’t! For me foo_id was filled with a 1. Wait, where does this come from?
After I digged deep enough in Doctrine_Record, I saw that this was automatically assigned in the constructor, coming from a statically incremented $_index variable. I could revert this by using my own constructor and call assignIdentifier() like this:
class FooBarBaz extends BaseFooBarBaz
{
public function __construct()
{
parent::__construct();
$this->assignIdentifier(false);
}
}
but now this object could no longer be added to a Doctrine_Collection (which is a bummer, because if you want to extend object lists with “default” empty objects, you most likely stumble upon a Doctrine_Collection, which is the default data structure returned for every SQL query).
So you might ask “Why the hell does all this impose a problem for you?”
Well, if you work with the FooForm created by the doctrine plugin for you in Symfony and you want to add FooBarBazForm via sfForm::embedFormForEach a couple of times (similar to the use case described here), you suddenly have the problem that your embedded form for the appended new FooBarBaz object “magically” gets a foo_id of a wrong (maybe not existing) Foo object and you wonder where the heck this comes from…
I have my lesson learned for the last one and a half days. I promise I’ll never ever create a table in Doctrine with a multi-key primary key again and I’m returing back to Propel for my next project.
Posted in Coding, Rants, Work | No Comments »