Récemment, mon apprenti a commencé à me rajouter dans chaque action de chaque contrôleur un même morceau de code qui régule un peu le flow d’execution:
public function executeMyAction(sfWebRequest $request)
{
$state = Account::getState();
if( $state == Account::ACCOUNT_NOT_READY )
$this->forward('mymodule', 'getready');
[...]
}
public function executeMyOtherAction(sfWebRequest $request)
{
$state = Account::getState();
if( $state == Account::ACCOUNT_NOT_READY )
$this->forward('mymodule', 'getready');
[...]
}
[...]
J’étais à la recherche d’une solution un peu plus ‘sexy’ et ne pas à modifier 30 contrôleurs si un jour j’avais besoin de modifier ce code. J’ai pensé à la fonction ‘preExecute‘, qui permet de lancer du code avant de rentrer dans une action, mais la portée ne se limite qu’au module. Je voulais quelque chose d’un peu plus global.
J’ai trouvé la solution en browsant le code de sfGuard: Il me suffit de créer un Filter utilisant cet extrait de code suivant:
{
[...]
if($this->isFirstCall())
{
// Je sais, ça a l'air d'être une fonction statique, n'en prenez pas compte, c'est moche (c).
if( Account::getState() == Account::ACCOUNT_NOT_READY )
{
$this->getContext()->getController()->forward('mymodule', 'getready')
throw new sfStopException();
}
}
$filterChain->execute();
}
Note: Initialement, j’avais mis des « throw new sfStopException(); ». Cela permet d’interrompre l’exécution des Filters, et donc de ne pas lancer d’autres possibles redirections et obtenir en final un résultat correct. Cependant, après discussion avec mon pote mirmo qui m’a dit que c’était pas top, je me suis rendu compte que forward faisait déjà le throw de l’exception:
public function forward($module, $action)
{
if (sfConfig::get('sf_logging_enabled'))
{
$this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Forward to action "%s/%s"', $module, $action))));
}
$this->getController()->forward($module, $action);
throw new sfStopException();
}
Alors au final, il suffit de retirer les exceptions, de faire un simple return des forward et de compléter notre sfFilter, ce qui donnera:
// extrait de apps/myapp/lib/activeUserFilter.class.php
class activeUserFilter extends sfFilter
{
public function execute($filterChain)
{
$moduleName = $this->getContext()->getModuleName();
$actionName = $this->getContext()->getActionName();
// We don't redirect if we are trying to call site/success.
if($this->isFirstCall() && ($moduleName != 'mymodule' && $actionName != 'success'))
{
$state = Account::getState();
if( $state == Account::ACCOUNT_NOT_READY )
{
return $this->getContext()->getController()->forward('mymodule', 'getready')
}
}
$filterChain->execute();
}
}
Enfin, on l’active juste en rajoutant ce sfFilter dans apps/myapp/config/filters.yml:
active:
class: activeUserFilter
Update:
Ayant eu à nouveaux des problèmes, j’ai trouvé une autre solution peut être un peu plus simple:
return $lastActionEntry->getActionInstance()->forward('...', '...');
A voir donc …
0 Comments.