Accéder au contenu principal

Les contrôleurs avec Symfony2

Retourner une réponse

Je vous l'ai dit de nombreuses fois depuis le début de ce cours : le rôle du contrôleur est de retourner une réponse.
Voici le contrôleur le plus simple qui soit, c'est le contrôleur qu'on avait créé dans un des chapitres précédents. Il dispose d'une seule méthode, nommée « index », et retourne une réponse qui ne contient que « Hello World ! » :
<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
  public function indexAction()
  {
    return new Response("Hello World !");
  }
}


La suite de ce chapitre est découpée en deux parties :
  • Les objets Request et Response qui vont vous permettre de construire une réponse en fonction de la requête ;
  • Les services de base qui vont vous permettre de réaliser tout le travail nécessaire pour préparer le contenu de votre réponse.
Manipuler l'objet Request
Les paramètres contenus dans les routes
Tout d'abord côté route, souvenez-vous, on utilisait déjà des paramètres. Prenons l'exemple de la route oc_platform_view :

# src/OC/PlatformBundle/Resources/config/routing.yml

oc_platform_view:
    path:      /advert/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:view }
    requirements:
        id: \d+

Ici, le paramètre {id} de la requête est récupéré par la route, qui va le transformer en argument $id pour le contrôleur. On a déjà fait la méthode correspondante dans le contrôleur, la voici pour rappel :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
  // …

  public function viewAction($id)
  {
    return new Response("Affichage de l'annonce d'id : ".$id);
  }
}

Voici donc la première manière de récupérer des arguments : ceux contenus dans la route.



Les paramètres hors routes
En plus des paramètres de routes que nous venons de voir, vous pouvez récupérer les autres paramètres de l'URL, disons, « à l'ancienne ». Prenons par exemple l'URL /platform/advert/5?tag=developer, il nous faut bien un moyen pour récupérer ce paramètre tag ! C'est ici qu'intervient l'objet Request.
Pour récupérer la requête depuis un contrôleur, vous devez réaliser une petite pirouette : il faut ajouter un argument à votre méthode avec le typehint Request comme ceci :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request; // N'oubliez pas ce use !
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
    public function viewAction($id, Request $request)
    {
        // Vous avez accès à la requête HTTP via $request
    }
}


Comment est-ce possible ? C'est en réalité le Kernel qui s'occupe de cela, car c'est lui qui dispose de la requête. Après avoir demandé au routeur quel contrôleur exécuter, et avant de l'exécuter effectivement, il regarde si l'un des arguments de la méthode est typé avec Request . Si c'est le cas, il ajoute la requête aux arguments avant d'exécuter le contrôleur.
Maintenant que nous savons récupérer la requête, voici comment récupérer les paramètres contenus dans l'URL :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
  // …

  // On injecte la requête dans les arguments de la méthode
  public function viewAction($id, Request $request)
  {
    // On récupère notre paramètre tag
    $tag = $request->query->get('tag');

    return new Response(
      "Affichage de l'annonce d'id : ".$id.", avec le tag : ".$tag
    );
  }
}

Et vous n'avez plus qu'à tester le résultat : /platform/advert/9?tag=developer.
Nous avons utilisé $request->query pour récupérer les paramètres de l'URL passés en GET, mais vous savez qu'il existe d'autres types de paramètres :

Type de paramètres
Méthode Symfony2
Méthode traditionnelle
Exemple
Variables d'URL
$request->query
$_GET
$request->query->get('tag')
Variables de formulaire
$request->request
$_POST
$request->request->get('tag')
Variables de cookie
$request->cookies
$_COOKIE
$request->cookies->get('tag')
Variables de serveur
$request->server
$_SERVER
$request->server->get('REQUEST_URI')
Variables d'entête
$request->headers
$_SERVER['HTTP_*']
$request->headers->get('USER_AGENT')
Paramètres de route
$request->attributes
n/a
On utilise $id dans les arguments de la méthode

Avec cette façon d'accéder aux paramètres, vous n'avez pas besoin de tester leur existence. Par exemple, si vous faites $request->query->get('sdf') alors que le paramètre sdf n'est pas défini dans l'URL, cela vous retournera une chaîne vide, et non une erreur.


Les autres méthodes de l'objet Request

Heureusement, l'objet Request ne se limite pas à la récupération de paramètres. Il permet de savoir plusieurs choses intéressantes à propos de la requête en cours, voyons ses possibilités.
Récupérer la méthode de la requête HTTP
Pour savoir si la page a été récupérée via GET (clic sur un lien) ou via POST (envoi d'un formulaire), il existe la méthode $request->isMethod() :

<?php
if ($request->isMethod('POST'))
{
  // Un formulaire a été envoyé, on peut le traiter ici
}

Savoir si la requête est une requête AJAX
Lorsque vous utiliserez AJAX dans votre site, vous aurez sans doute besoin de savoir, depuis le contrôleur, si la requête en cours est une requête AJAX ou non. Par exemple, pour renvoyer du XML ou du JSON à la place du HTML. Pour cela, rien de plus simple !

<?php
if ($request->isXmlHttpRequest())
{
  // C'est une requête AJAX, retournons du JSON, par exemple
}

Toutes les autres
Pour avoir la liste exhaustive des méthodes disponibles sur l'objet Request, je vous invite à lire l'API de cet objet sur le site de Symfony2. Vous y trouverez toutes les méthodes, même si nous avons déjà survolé les principales.

Manipuler l'objet Response

Décomposition de la construction d'un objet Response

Pour que vous compreniez bien ce qu'il se passe en coulisses lors de la création d'une réponse, voyons la manière longue et décomposée de construire et de retourner une réponse. Pour l'exemple, traitons le cas d'une page d'erreur 404 (page introuvable) :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
  // On modifie viewAction, car elle existe déjà
  public function viewAction($id)
  {
    // On crée la réponse sans lui donner de contenu pour le moment
    $response = new Response;

    // On définit le contenu
    $response->setContent("Ceci est une page d'erreur 404");

    // On définit le code HTTP à « Not Found » (erreur 404)
    $response->setStatusCode(Response::HTTP_NOT_FOUND);

    // On retourne la réponse
    return $response;
  }
}

Je ne vous le cache pas : nous n'utiliserons jamais cette longue méthode ! Lisez plutôt la suite.

Réponses et vues

Généralement, vous préférerez que votre réponse soit contenue dans une vue tel que le préconise l'architecture MVC. Heureusement pour nous, le service templating que nous avons déjà utilisé dispose d'un raccourci : la méthode renderResponse(). Elle prend en paramètres le nom du template et ses variables, puis s'occupe de tout : créer la réponse, y passer le contenu du template, et retourner la réponse. La voici en action :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
  public function viewAction($id)
  {
    // On utilise le raccourci : il crée un objet Response
    // Et lui donne comme contenu le contenu du template
    return $this->get('templating')->renderResponse(
      'OCPlatformBundle:Advert:view.html.twig',
      array('id'  => $id)
    );
  }
}

Et voilà, en une seule ligne, c'est bouclé ! Et nous pouvons même aller encore plus loin, le contrôleur lui-même dispose d'un raccourci pour utiliser cette méthode renderResponse, il s'agit de la méthode render qui s'utilise exactement de la même façon, la voici en action :

<?php

  public function viewAction($id)
  {
    return $this->render(
      'OCPlatformBundle:Advert:view.html.twig',
      array('id'  => $id)
    );
  }

C'est comme cela que nous générerons la plupart de nos réponses. Finalement, l'objet Response est utilisé en coulisses, nous n'avons pas à le manipuler directement dans la plupart des cas.
N'oubliez pas de créer la vue associée bien entendu :

{# src/OC/PlatformBundle/Resources/view/Advert/view.html.twig #}

<!DOCTYPE html>
<html>
  <head>
    <title>Affichage de l'annonce {{ id }}</title>
  </head>
  <body>
    <h1>Hello Annonce n°{{ id }} !</h1>
  </body>
</html>

Si vous ne deviez retenir qu'une seule chose de cette section, c'est bien cette méthode $this->render(), car c'est vraiment ce que nous utiliserons en permanence.

Réponse et redirection

Vous serez sûrement amenés à faire une redirection vers une autre page. Or notre contrôleur est obligé de retourner une réponse. Comment gérer une redirection ? Eh bien, vous avez peut-être évité le piège, mais une redirection est une réponse HTTP.
Pour simplifier la construction d'une réponse faisant une redirection, il existe l'objet RedirectResponse qui étend l'objet Response que nous connaissons bien, en lui ajoutant les entêtes HTTP qu'il faut pour que notre navigateur comprenne qu'il s'agit d'une redirection. Cet objet prend en argument de son constructeur l'URL vers laquelle rediriger, URL que vous générez grâce au routeur bien entendu.
Voyez par vous-même ce que cela donne comme code :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse; // N'oubliez pas ce use
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
  public function viewAction($id)
  {
    $url = $this->get('router')->generate('oc_platform_home');
   
    return new RedirectResponse($url);
  }
}

Essayez d'aller à l'adresse /platform/advert/5 et vous serez redirigés vers l'accueil !
À l'image de la méthode render, il existe également une méthode raccourcie pour faire une redirection depuis un contrôleur, il s'agit de la méthode redirect qui prend en argument l'URL. L'avantage est que vous n'avez pas à rajouter le use RedirectResponse en début de fichier :
<?php

public function viewAction($id)
{
  $url = $this->get('router')->generate('oc_platform_home');
   
  return $this->redirect($url);
}

Changer le Content-type de la réponse

Lorsque vous retournez autre chose que du HTML, il faut que vous changiez le Content-type de la réponse. Ce Content-type permet au navigateur qui recevra votre réponse de savoir à quoi s'attendre dans le contenu. Prenons l'exemple suivant : vous recevez une requête AJAX et souhaitez retourner un tableau en JSON :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
  public function viewAction($id)
  {
    // Créons nous-mêmes la réponse en JSON, grâce à la fonction json_encode()
    $response = new Response(json_encode(array('id' => $id)));

    // Ici, nous définissons le Content-type pour dire au navigateur
    // que l'on renvoie du JSON et non du HTML
    $response->headers->set('Content-Type', 'application/json');

    return $response;
  }

Testez le rendu en allant sur /platform/advert/5.







Commentaires

Posts les plus consultés de ce blog

cPanel DDOS attack - Mitigate Slowloris Attacks - mod_qos

Apache mod_evasive Mod_evasive is a module available for the Apache HTTP server that can automatically block attacks by rate-limiting any IP that sends too many requests in a short time. Start by installing the module from WHM’s  EasyApache 4  interface. Select the  Currently Installed Packages  profile, search for  mod_evasive  in the  Apache Modules  section, and then install it. The default settings are good for most servers, but you can tweak them further by editing the configuration file  /etc/apache2/conf.d/300-mod_evasive.conf . You can also whitelist specific IP addresses or classes, so legitimate requests are not blocked. Configure CSF to block attacks While  mod_evasive  works very well, it only protects the Apache webserver. In order to harden other services as well, you can install the free  ConfigServer Security & Firewall  (CSF), which also includes a WHM plugin. As the  root  user, install CSF with these terminal commands: cd /usr/src rm -fv csf.tgz wget https://down

Spool file is locked (another process is handling this message)

LOG: MAIN cwd=/usr/local/cpanel/whostmgr/docroot 4 args: /usr/sbin/exim -v -Mrm 1dUoey-0006YJ-3A Message 1dUoey-0006YJ-3A is locked LOG: skip_delivery MAIN Spool file is locked (another process is handling this message) To do this you can run the following commands. |exim -Mt 1dUoey-0006YJ-3A |exim -Mrm 1dUoey-0006YJ-3A I am also providing the following page in case you want more information regarding the exim command options. http://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html

Open Media Vault NAS change password

Known Root Password Login to the OMV using the root user and the current password via SSH or Console enter the following command passwd root The new password is now active. Unknown Root Password, but Admin Access to OMV GUI is Available In this scenario we still can help ourselves with the GUI. The method we use is, that we create a cron job for the root user which then resets the password. Navigate to System -> Cron Jobs Press the +Add button UN-tick the enabled box, so that the cronjob does not run automatically. put into the command field the following line, replace newpasswd with your password: echo "root:newpasswd" | chpasswd press okay select the newly created cron job Click the run button. in the opening window click the start button. It will shortly deactivate and activate again. open ssh or console and login as root with your new password. Root and Admin Password Unknown If you do not know the root password, you need to boot with a Li