Mon, 19 Jan 2009

CakePHP and a paradigm shift to a code generation based approach?

At my new job, I'm writing a quite full-featured web application.
I've choosen to use CakePHP.
Why? Well, it may be 2 years since I last used it, but I've followed the project and it's planet, and it seems to have matured and gained even more monumentum.
I want to use something that is widely used so there is plenty of stuff available for it, it's RAD, it's flexible and powerful.
I noticed things such as CLI support and documentation have improved tremendously too.

However, I find that still, the recommended (or at least "most commonly used") practices are not as efficient as they could be, and that emphasis is placed on the wrong aspects.
See, even though the bake tool has come a long way since I last used it, it's still used to "generate some standard models/controllers/views" and the developer can take it from there [further editing the resulting files himself].
Finetuning generated code by editing the templates (in fact, only views have templates; the php code of models and controllers is hardcoded in the scripts that generate them), is still an obscure practice...
Also, there are very few commandline switches (Right now you can choose your app dir, whether you want to bake a model,controller or view, and it's name.)
All other things (validation rules, associatons, index/view/edit/add actions/views, which components, overwrite yes/no etc) are all handled interactively.
There are also some smaller enoyances such as when you specify one option like the name of the model, it assumes you don't want interactivity and produces a model containing nothing more then the class definition and the membervariable $name, which is usually worthless.
One thing that is pretty neat though, If you update $this->recursive in a model, the baked views will contain stuff for the associated things. But so much more could be done...


::Read from here

Ideallistically speaking, the bake tool (and it libraries) should imho become much more advanced:

  • templates for views, models and controllers.
  • choice of multiple (groups of) templates which you can choose with a commandline argument. (eg I typically have some different kinds of M/V/C's for a certain model, but there are many similarities and they can often even be categorised into groups.)
  • the ability to control all aspects of the bake process through commandline switches (or config files). Both the things that are asked now but also $recursive level, behaviors you want to use for models, etc.
  • proper cmdline arg parsing (getline or something)

We could then do a paradigm shift to actually treat your models, views and controllers as uncritical "output" code which can be deterministically regenerated (and hence doesn't need to be versionned), while the templates and the scripts to call bake become your "source", and your key asset to building the application you're working on.

If I had the time (or would use cake for personal projects) I would happily work on such refactorings in a clean way.
For now though, I've hacked/workarounded/patched the cake code in such a way that it behaves the way I want, while spending as little time on it as possible.
For those interested, the patched code is online at http://github.com/Dieterbe/cake/tree/master
The first rev is the original cakephp code, so you can look at the diffs if you want.

Changes until now ( http://github.com/Dieterbe/cake/commit/9ceb6234164ebc750c8b697a825834ca3... ):

  • Do not clear my terminal. (why is that needed anyway :/)
  • Some echo's that tell me which shells are loaded, tasks executed etc (to understand more how it all works)
  • always overwrite files. Hey I use version control! always bake unit tests, always bake all actions/views, except those for admin routing
  • never ask me which db to connect to, never use scaffolding, don't use helpers, don't write $useDbConfig to models (it's loaded dynamically in app_model),
  • agree with all associations except the hasOne's (I can build in exceptions/specific rules if I ever need them)
  • validation rules are specified as sql comments. I don't want to re-answer those questions each time I rebake.
See this example sql file. When baking a model, the code will first try to find a specific rule for the model, if not found, it will look for a global rule, and if still not found, ask the question interactively.
[code lang="sql"]
-- cake validate ALL id none
-- cake validate ALL created none
-- cake validate ALL modified none
(...)
CREATE TABLE foos (
id serial NOT NULL,
name character varying(255) NOT NULL, --cake validate apc alphanumeric
type character varying(255) NOT NULL, --cake validate apc notempty
room_id integer NOT NULL, --cake validate apc numeric
created timestamp without time zone,
modified timestamp without time zone
);
[/code]

Here is the bash code which I currently use to bake all my models without any interactivity:

[code lang="bash"]
for i in `cake bake model <<< 'q' | awk '/^[[:digit:]]/ {print $2}'` #get a list of all models
do
if [ $i != Aro ] && [ $i != Aco ] && [ $i != ArosAco ]
then
echo ">>> doing $i...."
cake bake model $i
fi
done
[/code]

I may post later again about this stuff if I have something useful to say.

Comments

Have you ever tried Symfony? I've worked with it before, but never was interested enough in CakePHP to try it out.. Maybe if you have used both already, you might be able to give some pro's and con's on both :)

Bart

Yeah, when I wrote my thesis I did a comparision of some frameworks.
Symphony was in the list too. Iirc I didn't choose it because I found it too complicated. Eg all the configuration options, the ORM layer with xml configuration etc. Also, I seem to remember the codebase of the framework itself was much bigger, so less easy to get into :-)

console/libs/tasks/model.php Line 248: + exec("awk '/[[:blank:]]$fieldName.*cake validate $modelname/ {print \$NF}' /home/dieter/code/crm/branches/dieter/code-misc/colomanager.sql",$output,$exit);

Would you be so kind as to provide this file? /home/dieter/code/crm/branches/dieter/code-misc/colomanager.sql

Your changes are slightly useless without it.

This is the SQL file you were talking about? It would be nice to get some more documentation, and use an actual config file. I will probably add that now.


Name:


E-mail:


URL:


Comment:


What is the first name of the guy blogging here?


This comment form is pretty crude. Make sure mandatory fields are entered correctly.
Basic html tags (a,i,b, etc) are allowed, others are sanitized