Créer un champ date qui peut afficher la date au format local n'est pas si simple avec le Zend Framework. Voyons un peu comment procéder.
Zend_Date ne supporte pas pour l'instant le format de date utilisé par MySQL car l'équipe qui développe le ZF ne souhaite pas alourdir encore un peu plus le code du composant avec des constantes adaptées à toutes les bases de données. Mais ce n'est pas un problème, puisqu'on a le code source. Il suffit d'étendre la classe Zend_Date :
<?php
class Wiip_Date extends Zend_Date
{
const MYSQL_DATE = 'yyyy-MM-dd';
const MYSQL_DATETIME = 'yyyy-MM-dd HH:mm:ss';
}
?>
Mise à jour du 4/12/09 : remplacé Y par y dans les codes de format de la date (http://wiip.fr/content/subtilit-de-zend-date).
Voilà, comme ça on dispose de deux constantes qui vont nous être utiles pour la suite. On peut en profiter pour ajouter d'autres méthodes utiles.
Lorsqu'on récupére les données de notre formulaire pour les sauvegarder, on doit convertir la date du format local (JJ/MM/AA pour la France) au format de la base de données (AAAA-MM-JJ pour MySQL). Pour cela, on peut ajouter un filtre à notre élément de formulaire.
<?php
class Wiip_Filter_LocalDateToMysql implements Zend_Filter_Interface
{
public function filter($value)
{
if (Zend_Date::isDate($value, Zend_Date::DATE_SHORT)) {
// La valeur correspond bien à une date au format local court
// On crée un objet date ...
$date = new Zend_Date($value, Zend_Date::DATE_SHORT);
// ... et on le convertit au format MySQL
return $date->toString(Wiip_Date::MYSQL_DATE);
}
return $value;
}
}
?>
Pour utiliser ce filtre dans un élément de formulaire, il faut ajouter le chemin du composant aux chemins de recherche de plugin de l'élément :
<?php
// Pour tout le formulaire (à appeler dans la méthode init par exemple)
$this->addElementPrefixPath('Wiip_Filter', 'Wiip/Filter', Zend_Form_Element::FILTER);
// Pour un élément en particulier
$this->element->addPrefixPath('Wiip_Filter', 'Wiip/Filter', Zend_Form_Element::FILTER);
?>
Les filtres sont appliqués lors de l'appel à la méthode getValue de l'élément ou la méthode getValues du formulaire. Vous pouvez obtenir la valeur non filtrée en utilisant la méthode getUnfilteredValue de l'élément ou la méthode getUnfilteredValues du formulaire.
Avant d'écrire la date dans la base de données, il faut s'assurer qu'elle est bien valide car MySQL ne le fait pas. Le Zend Framework dispose d'un composant adapté à cette tâche : Zend_Validate_Date.
Il suffit de lui passer en option le format de la date à valider :
<?php
$val = new Zend_Validate_Date(Wiip_Date::MYSQL_DATE);
?>
Il nous reste une étape importante : charger la valeur lue dans la base de donnée dans notre élément de formulaire. Pour cela, on va écrire une aide de vue :
<?php
class Wiip_View_Helper_FormDate extends Zend_View_Helper_FormText
{
public function formDate($name, $value = '', $attribs = null)
{
if (!isset($attribs)) $attribs = array();
(isset($attribs['class'])) ? $attribs['class'] .= ' date' : $attribs['class'] = 'date';
if (!isset($attribs['maxlength'])) $attribs['maxlength'] = strlen(Zend_Date::DATE_SHORT);
if (!isset($attribs['size'])) $attribs['size'] = strlen(Zend_Date::DATE_SHORT);
if (Zend_Date::isDate($value, Wiip_Date::MYSQL_DATE)) {
$date = new Zend_Date($value, Wiip_Date::MYSQL_DATE);
$value = $date->get(Zend_Date::DATE_SHORT);
} elseif ($value == '0000-00-00') {
$value = '';
}
return parent::formText($name, $value, $attribs);
}
}
?>
L'aide de vue se charge de convertir la date MySQL au format local. Elle prédéfini également la largeur du champ (avec l'attribut size) et le nombre maximal de caractères autorisé ((avec l'attribut maxlength). On ajoute également une classe CSS date qui permet de personnaliser l'apparence du champ ou de lui appliquer une transformation avec Javascript.
Maintenant que tous les composants sont en place, on peut créer notre élément de formulaire :
<?php
class Wiip_Form_Element_Date extends Wiip_Form_Element_Text
{
public $helper = 'formDate';
public function init()
{
$this->addPrefixPath(
'Wiip_Filter',
'Wiip/Filter',
Zend_Form_Element::FILTER
);
$this->addFilter('LocalDateToMysql');
$val = new Zend_Validate_Date(Wiip_Date::MYSQL_DATE);
$this->addValidator($val);
}
}
?>
Voilà, c'est fini. On peut utiliser la même méthode pour un champ permettant la saisie combiné d'une date et d'une heure. J'espère que cet exemple vous aura permis de mieux comprendre le fonctionnement des filtres, validateurs et aides de vue sur un élément de formulaire basé sur Zend_Form.
Commentaires
Anonymous (non vérifié)
ven, 10/07/2009 - 11:44
Permalink
Ou places-tu ton filtre dans
Ou places-tu ton filtre dans l'architecture de base Zend Framework ?
Maxence
ven, 10/07/2009 - 12:19
Permalink
Dans le répertoire /library.
Dans le répertoire /library. Le chemin complet du fichier est /library/Wiip/Filter/LocalDateToMysql.php.
/library doit être dans include_path.
Anonymous (non vérifié)
ven, 10/07/2009 - 13:42
Permalink
Ok merci. Remarque, lorsque
Ok merci.
Remarque, lorsque l'on passe une date courante au format mysql, celle ci ressort avec l'heure bloquée à 0. Pour conserver l'heure courante, il faut modifier le filtre et le remplacer par cette ligne :
" $date = new Zend_Date($value, Zend_Date::ISO_8601); "
Maxence
ven, 10/07/2009 - 20:36
Permalink
Pour les datetime, j'ai un
Pour les datetime, j'ai un filtre adapté :
class Wiip_Filter_LocalDateTimeToMysql implements Zend_Filter_Interface
{
public function filter($value)
{
if (Zend_Date::isDate($value)) {
$date = new Zend_Date($value);
return $date->toString(Wiip_Date::MYSQL_DATETIME);
}
return $value;
}
}
moussa (non vérifié)
dim, 23/08/2009 - 02:17
Permalink
j'ai vu que tu étends une
j'ai vu que tu étends une classe(la classe Wiip_Form_Element_Tex) dont je vois pas la définition
Maxence
dim, 06/09/2009 - 18:03
Permalink
Très juste (il y en a un au
Très juste (il y en a un au moins qui suit). En fait, c'est juste une surcharge de Zend_Form_Element_Text avec des decorators personnalisés.
Martin (non vérifié)
sam, 21/11/2009 - 11:06
Permalink
Bonjour, Je n'arrive pas à
Bonjour,
Je n'arrive pas à mettre ton exemple en place, peux tu m'expliquer comment tu définis le Wiip_View_Helper_FormDate ?
Merci
Maxence
dim, 29/11/2009 - 09:18
Permalink
Pour que
Pour que Wiip_View_Helper_FormDate fonctionne, il faut que le fichier FormDate.php soit placé dans /library/Wiip/View/Helper/, que l'espace de nom Wiip soit déclaré dans l'autoloader et que le préfixe soit enregistré au niveau du formulaire ou de l'élément comme je l'explique plus haut.
Si tu utilises Zend_Application, il faut ajouter l'espace de nom Wiip dans /application/configs/application.ini :
[..]
; Espaces de noms
autoloadernamespaces.0 = "Zend"
autoloadernamespaces.1 = "Wiip"
[..]
Alex (non vérifié)
ven, 12/02/2010 - 17:52
Permalink
Super cool, grâce a votre
Super cool, grâce a votre article j'ai enfin compris comment en peut définir le Wiip_View_Helper_FormDate.
Amicalement
betclic
Martin (non vérifié)
mer, 26/05/2010 - 10:15
Permalink
J'avais zappé l'ajout du
J'avais zappé l'ajout du changement de formatage de date (YYYY -> y)
Enfin la première fois que je suis passé il n'y étais pas. Du coup mon code ne fonctionnait que de façon aléatoire.
Tu devrais le mettre en plus gros je pense, ou changer l'exemple ;-)
Ajouter un commentaire