Blog
Mise en place d’une architecture REST avec Zend Framework 2

Partager


Si vous n’êtes pas encore familier avec Zend Framework 2, je vous conseille de suivre dans un premier temps le tutoriel de base relativement bien expliqué par la team de ZF2. Ce tutoriel explique les fondamentaux, à savoir les routes, les modules, les controllers et les vues : http://zf2.readthedocs.org/en/latest/user-guide/modules.html Si vous êtes intéressé par un tutoriel de base pour prendre en main ZF2, n’hésitez pas à commenter cet article pour en faire la demande.

Installation rapide de ZF2

Si vous avez déjà installé ZF2 et que vous connaissez la procédure vous pouvez vous rendre au paragraphe suivant.

Zend Framework utilise le système « composer » pour gérer ses dépendances. Vous pouvez télécharger l’installeur windows à l’adresse suivante http://getcomposer.org/Composer-Setup.exe. Ensuite il vous faut récupérer le framework, vous pouvez le télécharger en version de base, l’essentiel y est, à l’adresse suivante : https://github.com/zendframework/ZendSkeletonApplication. Si vous n’êtes pas familier avec GIT, vous pouvez télécharger l’archive ZIP. Ensuite il faut exécuter « composer » à la racine de notre nouveau répertoire, afin qu’il puisse mettre à jour toutes les dépendances :
php composer.phar install
N’oubliez pas de configurer votre vhost si vous êtes sous Apache et de configurer le « directory » sur le répertoire « public ».

One rule to rule them all

Dans cette deuxième mouture de Zend Framework il est maintenant possible de configurer les routes à travers un fichier de configuration. Dans notre exemple, nous allons nous servir du module de base du framework, à savoir le module « Application ». Dans le fichier module.config.php, il faut créer une route qui va être mappée sur un nouveau controller que nous allons appeler « WineController ». Ajoutons cette route au fichier module.config.php :
'application' => array(
	(...)
),
‘wine_road’ => array(
	‘type’ => ‘Segment’,
	‘options => array(
		‘route’ => ‘wine[/][:slug[/]]’,
                constraints’ => array(
			'slug' => '[a-zA-Z0-9-_]+',
		),
		‘default’ => array(
			‘controller’ => ‘Application\Controller\Wine’,
		)
	)
)
Sans oublier d’ajouter la ligne pour pouvoir appeler le controller :
‘controller’ => array(
	‘invokables’ => array(
		(...)
		' Application\Controller\Wine'	=> Application\Controller\WineController',
	)
)
Nous allons travailler sur l'url "/wine" afin de gérer une cave à vin virtuelle. Pour cela, nous avons besoin :
  • d'ajouter une nouvelle bouteille
  • de mettre à jour une bouteille (son prix, son année, son cépage)
  • de supprimer une bouteille ou un carton entier de bouteilles
  • de consulter une ou des bouteilles, avec un filtre (année par exemple) ou non

Rappel sur les différentes méthodes pour effectuer une requête http

Les derniers navigateurs supportent les 4 principales méthodes pour effectuer une requête http, à savoir :
  • GET : pour récupérer une ou des ressources vinicoles
  • PUT : nous allons nous en servir comme ‘update’ d’une ou des ressources vinicoles
  • POST : pour enregistrer une ou des nouvelles ressources vinicoles
  • DELETE : pour supprimer une ou des nouvelles ressources vinicoles
Tout va résider dans la façon d’effectuer notre requête http, et principalement son URL. En effet pour récupérer une ressource en particulier nous allons utiliser la méthode GET avec l’URL "/wine/sociando_mallet-42", alors que pour récupérer toutes les bouteilles nous allons effecteur un GET avec l’URL "/wine". Ensuite il va être possible d’effectuer un filtre sur notre appel, comme par exemple "/wine ?year=2013" pour récupérer toutes les bouteilles de l’année 2013.

WineController - méthode de vérification

Nous allons entrer dans le vif du sujet en créant notre controller « WineController » dans le dossier « Controller » du module « Application ». Notre controller doit étendre la classe abstraite « AbstractRestfulController » de Zend. Nous allons y ré-implémenter différentes méthodes qui vont nous être très utiles. Tout d’abord, la première méthode, qui est la plus important, est « setEventManager ». Zend passera en premier dans cette méthode, elle va nous permettre d’écouter les événements générés par Zend, en particulier l’event « dispatch ». Cet événement est généré lorsque Zend a matché une route et qu’il la dispatch vers une des actions de notre controller. Ainsi avant de rentrer dans n’importe quelle action, il va entrer aussi dans la méthode checkOptions car nous lui avons attaché l’evenement dispatch. Un peu de code vaut mieux qu’un long discours :
class WineController  extends AbstractRestfulController 
{
	// methode liste, ex : "/wine"
	protected $collectionMethod = array('GET'); 
	// methode unitaire, ex : "/wine?slug=sociando_mallet-42"
	protected $ressourceMethod = array('GET', 'POST', 'PUT', 'DELETE'); 
	
	public function setEventManager(EventManagerInterface $events) {
		parent::setEventManager($events);
		$events->attach('dispatch', array($this, 'checkMethod'), 10);
	}
	
	protected function _getMethod() {
		if ($this->params()->fromRoute('slug', false)){
			return $this->ressourceMethod;
		}
		return $this->collectionMethod;
	}

	public function checkMethod($e) {
		if (in_array($e->getRequest()->getMethod(), $this->_getMethod())){
			return;
		}
		$response = $this->getResponse();
		$response->setStatusCode(405);
		return $response;
	}
	
	public function options() {
		$response = $this->getResponse();
		$response->getHeaders()
		->addHeaderLine('Allow', implode(',', $this->_getMethod()));
		return $response;
	}
}
Si le slug est présent dans l’URL nous allons autoriser tous les types de méthode alors que pour une collection (une liste) nous n'allons autoriser que la consultation. C'est le rôle de la méthode "checkMethod". Elle donne comme code d'erreur 405 si la méthode n'est pas la bonne. La méthode "options" permet de répondre à une requête de type "OPTIONS". Je vous invite à l'essayer.

WineController - méthodes REST

Il faut implémenter certaines méthodes qui vont répondre aux différentes requêtes HTTP :
class WineController  extends AbstractRestfulController 
{
	(...)
	// Consulter une liste de bouteilles
	public function getList()
	{	
		// On récupère les paramètres de la query
		$params = $this->params()->fromQuery();
		// Si on ajoute le paramètre 'year', on peut filtrer par année
		if (isset($params['year'])
		// On filtre la requête par année
	}
	
	// Consulter une bouteille en particulier
	public function get($slug)
	{	
	}
	
	public function update($slug, $data)
	{
		//$data['year']
		//$data['price']
	}

	public function create($data)
	{
	}
	
	// Delete sur une ressource
	public function delete($slug){
	}
	
	// Delete sur une collection
	public function deleteList(){
	}
}
Dans cet article je ne détaille pas toute la partie interaction avec le model et notre base de donnée, je vous laisse libre à votre implémentation. Un prochain article sera disponible à ce sujet. Il nous reste une dernière chose à effectuer afin que Zend puisse comprendre le paramètre "slug" et non pas "id" qui est le paramètre par défaut. Il faut ajouter cette ligne de code dans la méthode "checkMethod".
$this->setIdentifierName('slug');
Afin de faciliter notre travail, il existe une extension nommée "RESTClient" sur firefox ou "Advanced REST client" sur chrome qui permet d'effectuer rapidement et facilement des requêtes http "à la main". Côté client vous pouvez utiliser un framework javascript tel que Angular pour communiquer avec notre API. Un exemple est fourni dans cet article.
comments powered by Disqus