When I was thinking about the MVC separation concerns some people have with symfony I came across something that I noticed in most of my actions that seem like a violation of MVC logic. In almost every action I do a database lookup. Not only is that more a part of the controller, rather than the view (I consider the view made up action and template), but also Java Frameworks can do dependency injection (which works declarative rather than programmatic).

So I was thinking of a User Edit action. It usually looks like

$this->user = UserPeer::retriveByPK(this->getRequestParameter('user'));
$this->forward404Unless($this->user);

I would assume that 2/3 of the actions in all symfony applications have similar lines at the beginning. And its not only extra effort to code these two lines every action, you also put code into that somehow fulfills a different purpose. The action should assume that the user to edit is already retrieved.

As a solution for those issues I propose the use of sfPopulatedRouting. It uses the exact configuration as the current sfPatternRouting (standard routing.yml file), but it treats the requirement differently.

Ideally this would be only a slim extension on top of sfPatternRouting, but I had quite a lot of issues extending the class. As I see the implementation anyway just as a proof of concept this is okay and can be fixed later on. Using that new routing your action will look like:

$this->user = this->getRequestParameter('user');

I came up with the idea to recycle the requirements parameters in routing as the meaning does nicely overlap :-) . Here an example:

edit_user:
  url:  /edit/:user
  param: { module: user, action: edit }
  requirements: { user: UserPeer::retrieveByPk }

As you see it will use propel pk getter to return the user from the Peer object. Even though the use of slugs is widespread, also many people use the PK in the url. for that you can use the better shortcut:

edit_user:
  url:  /edit/:user
  param: { module: user, action: edit }
  requirements: { user: User }

Ideally this would detect your ORM and perform the right query.

you can find the prototype sfPopulatedRouting.class.php and a diff file (against sfPatternRouting) here.
(requiring php 5.2.3 due to call_user_func() signature)

Let me know what you think of this, and if you have any good idea on for example auto publish the parameters to the action. Because

$this->user = this->getRequestParameter('user');

doesn’t look like injected. But making it

echo $this->user->getName();

requires modifying code of the action dispatcher. Something like the bad register_globals :-)