Laravel : ignorer une règle de validation unique lors d’un update

Un petit point de base manquant dans les règles de validation d’un formulaire du framework Laravel est le cas où on veut ignorer un champ unique lors d’une mise-à-jour. Je m’explique. Prenons le début d’une classe modèle de gestion d’utilisateurs avec les règles de validation dans un attribut statique comme suit :

class User extends Eloquent
{
	public static $rules = array(
		'name'					=> 'required|alpha|min:2',
		'username'				=> 'required|alpha|min:2',
		'email'					=> 'required|email|unique:users,email',
		'password'				=> 'required|alpha_num|between:6,12|confirmed',
		'password_confirmation'	=> 'required|alpha_num|between:6,12'
	);
	
	// ...

On voit que l’email doit être unique, pas de problème lors de l’ajout, mais lorsque l’on met à jour un utilisateur, cette règle nous bloque, car l’email doit être unique. Il existe un moyen d’ignorer un certain ID en l’ajoutant à la fin, comme ceci 'required|email|unique:users,email,10', mais il est difficile d’ajouter cet ID dynamiquement dans le modèle sans ajouter du bruit à notre code. Une solution consiste à laisser le modèle en l’état, mais de hacker cet élément du tableau de règle depuis la méthode d’update du controlleur :

public function postUpdate($id)
{
	$user = User::find($id);

	// On récupère les règles
	$userrules = User::$rules;
	
	// On met à jour la règle pour le champ email avec l'ID courant
	$userrules['email'] = 'required|email|unique:users,email,' . $id;

	// Validation des champs
	$validator = Validator::make(Input::all(), $userrules);

	if ($validator->passes()) {
	
	// ...

Il semble un peu bizarre que ce mécanisme ne soit pas pris en compte par défaut dans Laravel, en espèrant qu’il le soit dans une prochaine version.

Laravel 4 et Ajax

Dans cet article, voyons comment implémenter une requête Ajax (XHR) avec le framework Laravel.

Implémenter une requête Ajax au sein d’un projet Laravel n’est pas bien compliqué. Dans ce bref exemple, j’ai un tableau de données (non présent dans le billet), un des champs est une icône de statut de l’enregistrement qui peut-être actif ou non, et lorsque l’on clique sur ce bouton, l’état bascule en faisant une requête XHR.

La partie javascript va se trouver dans la vue en question (celle qui affiche le tableau). Lorsque le bouton est cliqué, jQuery.ajax() va déclencher l’exécution de l’action getToggleVisibility() du controlleur courrant, DasboardController dans notre exemple, celui-ci va retourner une réponse JSON qui est utilisée pour intéragir sur la vue. Et le tour est joué.

Continuer la lecture de « Laravel 4 et Ajax »

L’objet Zend_Db_Select

L’objet Zend_Db_Select du framework Zend (ZF1) sert à représenter une requête SQL de type SELECT incluant des méthodes orientées objets permettant de construire une requête morceau par morceau. Ce court billet détaille un peu la construction d’une requête incluant sous-requête et jointure.

La requête SQL

Voici le SQL que nous voulons représenter à la façon Zend_Db_Select. Pour avoir une idée du schéma, on dispose d’une base de données représentant une gestion de biens, certains biens pouvant être groupés (par exemple, on choisit de grouper des biens individuels CPU, RAM et carte mère dans un bien ordinateur). Cette requête rapatrie ces groupes. On sélectionne les biens de type group d’une table goods (ayant un champ group égal à GRP), le détail des articles sont extraits de la table articles (JOIN) et on compte le nombre d’articles dans le groupe :

SELECT
	aa.*,
	(SELECT COUNT(barcode) FROM goods WHERE group = aa.barcode) AS items
	FROM (
		SELECT a.description, g.* FROM goods AS g
		JOIN articles AS a ON a.code = g.code
			WHERE g.group = "GRP"
	) aa

Rien de bien compliqué SQLement parlant, mais la traduction en utilisant Zend_Db_Select peut être un peu délicate, au début.

Objets Select

L’opération consiste à découper toutes chaque sous-requête et de les assembler à la fin. Voici le code :

// Première requête avec JOIN
$s1 = $db->select()
		->from(
			array('g' => 'goods'),
			array(
				'barcode',
				'quantity',
				'price'
			)
		)
		->join(
			array('a' => 'articles'),
			'a.code = g.code'
		)
		->where('g.group = ?', 'GRP');

// Requête contenant le COUNT
$s2 = $db->select()
		->from(
			'goods',
			array('COUNT(barcode)')
		)
		->where('group = ?', new Zend_Db_Expr('aa.barcode'));

// On assemble le tout
$select = $db->select()
		->from(
			array('aa' => new Zend_Db_Expr('(' . $s1 . ')')),
			array(
				'aa.*',
				'items' => new Zend_Db_Expr('(' . $s2 . ')')
			)
		);

$resultSet = $db->fetchAll($select);

On voit que $s1 représente le SELECT qui liste les groupes, contenu dans le SELECT principal. $2 est celui qui compte le nombre d’article(s) dans un groupe. Et enfin on assemble tout cela dans le $select final que l’on peut exécuter.
A noter l’utilisation de Zend_Db_Expr pour injecter une simple expression.

Conclusion

Manipuler des requêtes un peu complexes avec ZF peut faire peur de prime abord et on peut vouloir se rabattre sur des requête brutes (en utilisant directement Zend_Db_Statement par exemple avec query()), mais lorsque l’on met un peu les mains dedans, c’est un outil tout à fait avancé et puissant qui permet de faire beaucoup de choses tout en restant à manipuler des objets.

Voyons un peu le composant Zend_Barcode du Zend Framework

Un de mes projets Zend Framework depuis plusieurs mois déjà est une application web de gestion de stock, celle-ci gère bien entendu les codes-barres des biens. Dans cet article nous allons voir comment les créer avec ZF. Pour une fois ce tutoriel va utiliser des composants ZF dans un projet autonome et non au sein d’un projet MVC complet.

Continuer la lecture de « Voyons un peu le composant Zend_Barcode du Zend Framework »