Zend_Db_Table_Row : transformer les colonnes de type date en objet Zend_Date

Logo Zend Framework

Le module Active Record de Rails convertit les colonnes de type date en instance de la class Date de Ruby. On peut très simplement faire la même chose avec Zend_Db_Table_Row. Il suffit de surcharger la méthode magique __get.

<?php
class Wiip_Db_Table_Row_Abstract extends Zend_Db_Table_Row_Abstract
{
    public function 
__get($columnName)
    {
        
$m $this->_table->info('metadata');

        if (isset(
$m[$columnName])) {
            
$value $this->_data[$columnName];
            switch (
$m[$columnName]['DATA_TYPE']) {
                case 
'date':
                    if (
$value and ($value != '0000-00-00')) {
                        
$date = new Wiip_Date($valueZend_Date::ISO_8601);
                        
$date->setTime('00:00:00');
                        return 
$date;
                    } else {
                        return 
null;
                    }
                    break;

                case 
'datetime':
                    if (
$value and ($value != '0000-00-00 00:00:00')) {
                        return new 
Zend_Date($valueZend_Date::ISO_8601);
                    } else {
                        return 
null;
                    }
                    break;

                default:
                    return 
parent::__get($columnName);
            }
        } else {
            return 
parent::__get($columnName);
        }
    }
}
?>

Pour les champs de type date j'utilise une classe dérivée de Zend_Date car la méthode __toString de cette dernière renvoie la date avec l'heure. La classe ci-dessous modifie ce comportement pour renvoyer uniquement la partie date.

<?php
class Wiip_Date extends Zend_Date
{
    public function 
__toString()
    {
        return 
$this->toString(Zend_Date::DATE_MEDIUM);
    }
}
?>

Une fois ce code mis en place, on peut utiliser des objets dérivés de Wiip_Db_Table_Row_Abstract de façon très intuitive :

<?php
echo $row->date// Affiche par exemple 6 juin 2009

if ($row->date->isToday()) {
  echo 
'Aujourd\'hui';
} else {
  echo 
$row->date;
}

$today = new Zend_Date();
if (
$row->date->isEarlier($today)) {
  echo 
'En retard';
}

echo 
$row->datetime// Affiche par exemple 6 juin 2009 15:59:33
?>

Si vous avez besoin d'obtenir la valeur de la colonne telle qu'elle est renvoyée par la base de données, vous pouvez passer par la méthode toArray qui n'est pas affectée par notre surcharge de __get.

<?php
$data 
$row->toArray();
echo 
$data['date']; // Affiche 2009-06-06
?>

Comme vous vous servez certainement de cette méthode pour charger les données dans vos formulaires basés sur Zend_Form (avec par exemple <?php$form->setDefaults($row->toArray()) ou $form->populate($row->toArray()?>), le fonctionnement de ces derniers ne sera pas perturbé.

A lire également

Commentaires

Niveau performance Zend_Date est très gourmand non ?
N'y a t il par un risque de perdre beaucoup ?

Déjà, il faut activer le cache pour Zend_Date (Zend_Date::setOptions(array('cache' => $adapter));). Ensuite, tout dépend de l'application. Mais dans les cas où la performance est critique, on récupérera certainement plutôt les résultats sous la forme d'un tableau et on ne passera donc pas par Zend_Db_Table_Row. Autre alternative, on peut utiliser la classe PHP DateTime (disponible depuis PHP 5.2.0) qui devrait être plus rapide, puisque c'est en natif dans PHP (d'ailleurs, cet article semble confirmer ce point).

je trouve cette astuce trés interressante ( de plus, jai fait d'autres cas propres à mes besoins). Seulement je n'arrive pas à l'utiliser. Toute mes tables sont déclarées en extend de zend_db_table_extract. Ou est ce que je lui dit d'utiliser Wiip_Db_Table_Row_Abstract (Je précise, je débute en zend)

merci de votre aide

Ajouter un commentaire