====== 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 :
''$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.
= $this->post->title; ?>
===== 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/