Suivant votre projet Symfony, souhaitez peut-être automatiser certaines tâches. Par exemple, vous souhaitez vous envoyer automatiquement un mail à vos utilisateurs qui ne se sont pas connectés du mois sur votre site. Autre exemple, et c’est celui que je vais garder, vous avez un site de e-commerce et vos utilisateurs créent un panier dans votre base de données au cours de leur visite. manque de chance, le visiteur ne finalise jamais sa commande. On va donc chercher à supprimer tous les soirs les commandes non-validées depuis un certains temps (par exemple, est-il pertinent de garder en base de données toute commande non-validées depuis plus 3 semaines – vous pourriez bien sûr envisager d’automatiser une analyse : quel type de panier n’est pas validé, avec quel produit, juste avant de supprimer ces paniers).
On va partir du principe que les éléments à supprimer sont dans la table “Panier”. La seule contrainte pour la suite c’est que celle-ci soit timestampable, donc avec un champs updated_at qui sera un timestamp Doctrine.
Création de la tâche
On va chercher une tache Symfony pour que l’on ait juste à taper ./symfony panier:supprime-vieux –nb-weeks=5 pour supprimer la panier plus vieux que 5 semaines (pour symfony ça va se traduire par appeler la tâche supprime-vieux de l’espace de nom panier). Pour ça on crée une nouvelle tâche avec Symfony :
./symfony generate:task panier:supprime-vieux
Symfony vient de vous créer un fichier lib/task/panierSupprimevieuxTask.class.php que nous éditerons plus tard.
Préparation de la classe PanierTable
Pour que le code soit le plus élégant possible, on va faire en sorte que pour supprimer les éléments désirés on ait juste une fonction de la classe PanierTable à appeler. Éditez donc le fichier lib/model/doctrine/PanierTable.class.php pour y ajouter ceci :
/**
* Delete old paniers.
*
* @param days int Age in days of the Paniers to keep
* @param status string Status of Panier to delete
* @return int Number of deleted Paniers
*/
public static function deleteOlds($days, $status = "attente") {
$q = self::getInstance()->createQuery('p')
->delete()
->where('p.status = ?', $status)
->where('p.created_at < ?', date('Y-m-d H:i:00', time() - 86400 * $days));// Ne pas oublier l'heure
return $q->execute();
}Voilà , ni plus ni moins, en appelant PanierTable::deleteOlds() vous allez supprimer les paniers vieux de plus de 21 jours.
Configuration de la tâche
Il ne reste plus qu’à éditer le fichier lib/task/panierSupprimevieuxTask.class.php.
Ajoutez ceci à la fonction configure, dans $this->adoptions juste après le // add your own options here, pour rajouter l’option –nb-weeks :
new sfCommandOption('nb-weeks', null, sfCommandOption::PARAMETER_REQUIRED, 'Maximum age in weeks of the items to keep', '3'),Il ne nous reste plus qu’à appeler notre fonction qui va supprimer les anciens paniers. Ajoutez donc ceci à la fonction execute, juste après le // add your code here :
$count = PanierTable::deleteOlds($options['nb-weeks']*7);
$this->logSection('paniers', "$count supprimés @ ".date('Y-m-d G:i', time()));
$count = PanierTable::deleteOlds(($options['nb-weeks']+2)*7, "valide");
$this->logSection('paniers', "$count validés mais non-payés supprimés @ ".date('Y-m-d G:i', time()));Votre fichier devrait donc ressembler à ceci :
<?php
class panierSupprimevieuxTask extends sfBaseTask
{
protected function configure()
{
// // add your own arguments here
// $this->addArguments(array(
// new sfCommandArgument('my_arg', sfCommandArgument::REQUIRED, 'My argument'),
// ));
$this->addOptions(array(
new sfCommandOption('application', null, sfCommandOption::PARAMETER_REQUIRED, 'The application name'),
new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
new sfCommandOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'doctrine'),
// add your own options here
new sfCommandOption('nb-weeks', null, sfCommandOption::PARAMETER_REQUIRED, 'Maximum age in weeks of the items to keep', '3'),
));
$this->namespace = 'panier';
$this->name = 'supprime-vieux';
$this->briefDescription = '';
$this->detailedDescription = <<<EOF
The [panier:supprime-vieux|INFO] task does things.
Call it with:
[php symfony panier:supprime-vieux|INFO]
EOF;
}
protected function execute($arguments = array(), $options = array())
{
// initialize the database connection
$databaseManager = new sfDatabaseManager($this->configuration);
$connection = $databaseManager->getDatabase($options['connection'])->getConnection();
// add your code here
$count = PanierTable::deleteOlds($options['nb-weeks']*7);
$this->logSection('paniers', "$count supprimés @ ".date('Y-m-d G:i', time()));
$count = PanierTable::deleteOlds(($options['nb-weeks']+2)*7, "valide");
$this->logSection('paniers', "$count validés mais non-payés supprimés @ ".date('Y-m-d G:i', time()));
}
}Vous pouvez donc maintenant tester ./symfony help panier:supprime-vieux et bien sur lancer ./symfony panier:supprime-vieux.
Cron
Il ne reste plus qu’à configurer cron pour lancer le bouzin quand vous le voulez. Pour ça rien d’excentrique, on lance dans son terminal (Unix oblige) crontab -e, et on ajoute la ligne suivante (en appliquant évidemment vos variantes pour coller à votre installation et l’heure où vous souhaitez lancer le truc, là il se lancera à 23h30 tous les soirs) :
30 23 * * * php /chemin/vers/symfony panier:supprime-vieux --nb-weeks=2
Voilà , c’est terminé !
Have fnu coding!
Références
- Billet de Riad Benguella sur le même sujet
- Pratical Symfony, jour 11 pour le cleanup (qui au passage comporte une erreur, si on oublie l’heure dans le timestamp le test échoue et rien n’est supprimé)
- Page Wikipedia sur Crontab










Bonjour pierre
Un grand merci pour ces posts c’est fantastique
Merci à toi pour ton commentaire encourageant :D