[Agavi-Dev] Doctrine 1.2 Attribute Configuration

28 views
Skip to first unread message

David Zülke

unread,
Jan 2, 2010, 2:10:40 PM1/2/10
to Agavi Dev Mailing List, Agavi Users Mailing List
Hi everyone,

Doctrine 1.2 dropped support for strings in attribute names and
values, without deprecating the functionality first in Doctrine 1.1
(which in my opinion is typical of this project, but that's a
different story).

That means that this:

$con->setAttribute('validate', 'none');

which in Doctrine 1.0/1.1 essentially did:

$con->setAttribute(Doctrine::ATTR_VALIDATE, Doctrine::VALIDATE_NONE);

just does not work anymore, breaking existing code, but why would they
care...

I've been thinking about this for quite a while now (and got the
occasional outburst of anger and frustration with Doctrine during
that). The problem is that there are all kinds of possible values for
attributes:

$con->setAttribute(Doctrine_Core::ATTR_VALIDATE,
Doctrine_Core::VALIDATE_NONE);
$con->setAttribute(Doctrine_Core::ATTR_PORTABILITY,
Doctrine_Core::PORTABILITY_ALL ^ Doctrine_Core::PORTABILITY_RTRIM);
$con->setAttribute(Doctrine_Core::ATTR_QUOTE_IDENTIFIER, true);
$con->setAttribute(Doctrine_Core::ATTR_TABLE_CLASS, 'MyTableClass');
$con->setAttribute(Doctrine_Core::ATTR_RESULT_CACHE, new
Doctrine_Cache_Db(array('connection' =>
Doctrine_Manager::connection(new PDO('sqlite::memory:')))));

The only solution I can think of right now that would solve this
properly is using literal expression strings for values, so to
configure the above, you would do:

<ae:parameter name="attributes">
<ae:parameter
name="Doctrine_Core::ATTR_VALIDATE">Doctrine_Core::VALIDATE_NONE</
ae:parameter>
<ae:parameter
name="Doctrine_Core::ATTR_PORTABILITY">Doctrine_Core::PORTABILITY_ALL
^ Doctrine_Core::PORTABILITY_RTRIM</ae:parameter>
<ae:parameter name="Doctrine_Core::ATTR_QUOTE_IDENTIFIER">true</
ae:parameter>
<ae:parameter name="Doctrine_Core::ATTR_TABLE_CLASS">'MyTableClass'</
ae:parameter>
<ae:parameter name="Doctrine_Core::ATTR_RESULT_CACHE">new
Doctrine_Cache_Db(array('connection' =>
Doctrine_Manager::connection(new PDO('sqlite::memory:'))))</
ae:parameter>
</ae:parameter>

There are two obvious problems with that:
1) how to validate the expression
2) how to evaluate the expression

For Agavi 1.1, we'll introduce special behavior for configuration
compliation where the config handler can talk to the class in question
for resolving of config parameters and other things; for instance,
AgaviPropelDatabase could do much of the merging, version juggling etc
at compile time rather than runtime. The same applies to
AgaviDoctrineDatabase, and that could *maybe* enable point #2 above,
although the idea so far was to only have all parameters filtered and
changed, not to have those "callbacks" actually determine the exact
code to be generated, which would be much, much harder to do. Either
way, validating the expressions won't really be possible, so a typo in
there would lead to very obscure parse errors in the generated
database configuration. Plus, having to put strings in quotation marks
would be awkward in my opinion (but necessary in order to avoid
conflicts with literals like "true" or "Doctrine_Core::VALIDATE_NONE",
both without quotation marks of course).

In any case, for Agavi 1.0, that option isn't on the cards. I'll now
change the code so that it checks if the key and/or value string is
defined as a constant, and if so, run it through constant(). That'll
allow the first, third and fourth of the attributes above to be
configured like this:
<ae:parameter name="attributes">
<ae:parameter
name="Doctrine_Core::ATTR_VALIDATE">Doctrine_Core::VALIDATE_NONE</
ae:parameter>
<ae:parameter name="Doctrine_Core::ATTR_QUOTE_IDENTIFIER">true</
ae:parameter>
<ae:parameter name="Doctrine_Core::ATTR_TABLE_CLASS">MyTableClass</
ae:parameter>
</ae:parameter>
(note how the table class does *not* have surrounding quotation marks).
The others would have to be done through subclassing
AgaviDoctrineDatabase, which like in case of the caching adapters is
arguably inconvenient as that might be one of the things you really
want to configure on a per-environment level.

The big question of course is whether that might actually be enough,
because the other cases are sufficiently special and/or rare that
people will subclass AgaviDoctrineDatabase anyway.

Another thing I have been considering is allowing people to specify a
class/function that is called during initialization of a connection
which would then deal with the above; I'm currently leaning towards
doing it that way, as it removes a lot of complexity.

Any kind of thoughts/feedback/input welcome. I'd really like to have a
long-term solution for this, which is why making a map of Doctrine's
attributes and then specifiying the behavior respectively is
completely out of the question - the project changes too quickly and
there is no attention to quality, backwards compatibility or API
stability for that to be viable.

- David

Reply all
Reply to author
Forward
0 new messages