Wednesday, November 11, 2009

Short remarks about " 30 symfony best practices "

Nicolas Perriault recently published some very interesting slides about symfony best practices.
I agree with 80% of the stuff pointed there but I've some doubts about the other 20%.

1. He says that using Doctrine_Query->execute() to obtain Doctrine_Records from the database is BAD because you should use fetchArray() method instead. This because you're supposed to have read-only data in your view.

I think it's often useful to fetch objects instead of arrays. The first reason is the possibility to delegate echoing to the __toString() method. If you have a Person Model and you already wrote a __toString() method to concatenate firstname and fullname for example, with arrays you're obliged to hardcode it every time ($person['name'].' '.$person['fullname']) in views. If one day you want to change it you have to go through all the occurrences. You can have a Person Helper to do something like "echo person_name($person)" but i find this an uglier way to promote "code reuse". When I want to be consistent, I'm used to delegate to __toString() and echo $objects.

Second reason: sometimes you have small test function in your models like $painter->hasColor('blue'). In my opinion you can safely use these small checks in your views without violating the MVC logic. Even designers will find those ones useful and clear.

Third reason: the Jobeet Tutorial uses objects everywhere and does not use fetchArray().

2. About "avoid using cache".

Hey, this sounds a little bit too drastic. Symfony runs with a huge overhead and it's probably
one of the slowest php framework around. If you want to obtain decent page loads in production, then using the cache is a must. If you think it's difficult to deal with it, well, you must do it anyway.

3. "There should never be any direct use of sfContext inside the Model layer. eg. sfContext::getInstance()"

Ok, that's true. But sometimes you cannot avoid it, really. For example, in the admin generator,
I doubt there's a way to filter results in table_method/peer_method based on user credentials
without calling sfContext (and table_method must belong to the Model).

More generally, you cannot "inject" objects in the admin generator Models
(read, auto_* classes). If you want to do that, you have to write your own.