La classe SActionController
Les contrôleurs vous permettent de définir des actions qui, après avoir rempli leur rôle, font le rendu d’un template ou redirigent vers une autre action. Chaque action est définie par une méthode publique qui sera rendu accessible lors d’une requête par le biais du Routing.
class BlogController extends SActionController { public function index() { $this->posts = Post::$objects->all(); } public function add_comment() { $comment = new Comment($this->params['comment']); $comment->save(); $this->redirect_to(array('action' => 'index')); } }
Par défaut, le contrôleur fera le rendu du template portant le même nom que l’action appellée, à moins que vous ne demandiez autre chose. Ainsi, dans l’action index de l’exemple ci-dessus, le controller fera le rendu du template /views/blog/index.php. Par contre, l’action add_comment qui n’est là que pour sauver dans la base un commentaire écrit par un visiteur n’a pas de vue associée. Elle effectue donc une redirection vers l’action index.
Request
Chaque requête faite au serveur est “wrappée” dans un objet SRequest. C’est cet objet qui est chargé notamment de déterminer le contrôleur et l’action demandés, en utilisant pour cela le Routing. L’instance de l’objet SRequest est accessible directement dans le controller en tant que propriété ($this→request).
Tous les paramètres de la requête, qu’ils viennent d’une requête GET ou POST, sont accessibles par le tableau $this→params.
Il est possible de construire des tableaux associatifs comme paramètres, en utilisant la notation entre crochets dans les fomulaires :
<input type="text" name="post[name]" value=""> <textarea name="post[comment]" />
$this→params[’post’] retournera un tableau avec les clés name et comment.
Response
Chaque action entraîne la création d’un objet SResponse, contenant toutes les variables d’instance que vous aurez définies dans l’action. Les valeurs de cet objet SResponse sont alors rendues disponibles dans le template.
public function view() { $this->post = Post::$objects->get($this->params['id']); }
La variable $this→post sera ainsi automatiquement disponible dans le template.
<h2><?= $this->post->title; ?></h2>
Sessions
Les sessions vous permettent de garder en mémoire des variables ou objets entre 2 requests.
$this->session['person'] = $user->name;
Génération de contenu
Comme nous l’avons vu plus haut, le rendu d’un template est automatiquement effectué après l’exécution d’une action. Si vous ne souhaitez pas utiliser ce comportement dans une action, plusieurs méthodes sont à votre disposition :
render_text($str)vous permet d’envoyer du texte au navigateur.render_file($path)vous permet de faire le rendu d’un template dont vous précisez l’emplacement.render_action($action)vous permet de faire le rendu d’un template correspondant à une autre action.
Redirections
Les actions qui mettent à jour le modèle doivent normalement rediriger vers une autre action. Une action save_post ne devrait par exemple pas afficher le post sauvé, mais rediriger vers une action show_post. Ainsi, si l’utilisateur rafraîchit la page dans son navigateur, le post ne sera pas sauvé 2 fois.
La méthode redirect_to prend en argument un tableau de paramètres permettant d’établir vers quels contrôleur et action rediriger, et d’ajouter des paramètres supplémentaires. L’URL utilisée pour la redirection est bien sûr réécrite grâce au Routing.
// nous sommes dans une action du controller blog $this->redirect_to(array('action' => 'edit', 'id' => 15)); // redirige vers /blog/edit/id/15 $this->redirect_to(array('controller' => 'comments', 'action' => 'delete_all', 'post_id' => 15)); // redirige vers /comments/delete_all/post_id/15
Filtres
Les filtres permettent d’exécuter du code avant ou après l’exécution de l’action. Vous pouvez par exemple les utiliser pour de l’audit, de l’authentification, etc...
Il est possible dans un filtre before de stopper l’exécution de l’action en retournant false ou en effectuant un rendu ou un redirect.
Les propriétés before_filters et after_filters sont des instances de la classe SFilterChain. Leur méthode append vous permet de spécifier des méthodes du controller comme filtres. Par exemple :
class MyController extends ApplicationController { public function __construct() { $this->before_filters->append('log_user_info'); } protected function log_user_info() { // logge l'IP et le navigateur de l'utilisateur... } }
Conditions
Les filtres peuvent être limités à certaines actions. Vous pouvez pour cela utiliser les options only et except.
class WeblogController extends ApplicationController { public function __construct() { // only require authentication if the current action is edit or delete $this->before_filters->append('authenticate', array('only' => array('edit', 'delete'))); } protected function authenticate() { // redirect to login page if not authenticated } }
Filter skipping
Dans certains cas, il est pratique de définir des filtres dans l‘ApplicationController qui s’appliqueront à tous les controllers, sauf à certains. Vous pouvez exclure les filtres dans ces controllers particuliers à l’aide de la méthode skip.
class ApplicationController extends SActionController { public function __construct() { $this->before_filters->append('authenticate'); } protected function authenticate() { ... } } class WeblogController extends ApplicationController { // will run the 'authenticate' filter } class MyController extends ApplicationController { public function __construct() { $this->before_filters->skip('authenticate'); } // will not run the 'authenticate' filter }
Around filters
Il est possible également de créer un filtre sous forme de classe, qui dispose de méthodes before et after. Une référence au controller sera passée en argument à ces méthodes.
class BenchmarkFilter { private $time_start = null; public function before($controller) { $this->time_start = microtime(true); } public function after($controller) { $time = microtime(true) - $this->time_start; $controller->logger->info("Processed in $time seconds.\n"); } } class WeblogController extends ApplicationController { public function __construct() { $this->around_filters->append(new BenchmarkFilter()); } }
Génération d'un contrôleur
Vous pouvez utiliser le script generate.php pour générer un nouveau contrôleur et créer le dossier des vues associées. Ouvrez une console et placez vous dans le répertoire de votre application (myproject/). Utilisez la commande suivante :
php scripts/do.php generate controller [controller_name] Exemple : php scripts/do.php generate controller posts -> crée un contrôleur posts_controller.php et un répertoire posts/ dans le répertoire app/views/
