Salut à tous, j'aurais une petite question à poser:

Est-il possible de trigger un evenement dans laravel (ou mysql) quand une date est passée dans le champ d'une table?

je m'explique, j'ai une table avec les champs champ date_debut , date_fin et state. Le state est en "pending" dès la création mais dois passer en "failed" dès que la date de fin est passée.

Est-il possible de trigger un evenement à la seconde ou la date de fin est passée (NOW()>= date_fin) afin de mettre le state à failed, ou doit-on obbligatoirement lancer une tâche cron toute les X minutes/heures... ?

J'espère avoir été assez clair =) et déjà merci de prendre le temps de lire ce post"

8 réponses


Azorgh
Réponse acceptée

Hello !

J'ai travaillé sur un projet sur lequel j'ai eu la même problématique.
Personnellement, j'ai choisi l'option du cron qui passe toutes les minutes pour changer le status en fonction des dates.

Pourquoi ? Simplement parce que le réponse que tu te poses n'a pas eu de réponse(s) pour moi, et dans un second temps, si tu as besoin de faire autre chose (on ne sait jamais dans 6 mois / 1 an) après avoir passé le statut en 'failed' (envoi d'email par exemple), et bien tu sera bien content d'avoir ta tache cron déjà en place !

Ca reste mon avis :)
Bon courage pour la suite ;)

Benares
Auteur

Ok merci c'est ce que je vais faire =)

Par contre y a-t-il un risque de ralentissement car cette BDD sera vraiment énorme (un aspect reseau social donc un ras de marée d'enregistrements =/)?

Etant donnée que tu execute tout ça côté serveur, tu pourrais limiter par exemple a chaque fois que le cron passe à 100 enregistrements.
C'est une méthode que j'utilise pour éviter de plomber le serveur.
Je rajoute un petit limit(100) dans la requête. Certes, toutes les données mettrons plus de temps à se modifier, mais dans ton cas, peut être que 100/minutes suffirait voir 200/300 au pires (rien de bien génant d'augmenter la limite).

Pour ma part, je ne pense pas qu'utiliser un CRON soit la solution idéal ici. Je n'ai peut être pas bien compris le problème mais j'aurai plutôt utilisé un observer Laravel pour gérer cela.

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Models\Observers\DateFinObserver;

class Statement extends Model
{
    public static function boot()
    {
        parent::boot();
        static::observe(new DateFinObserver);
    }
}

L'observer te permet ensuite de déclencher certaines actions (saving, saved...etc...) qui en quelque sorte marche comme des callbacks (before_save, after_update...etc...si tu connais un peu Rails). Tu trouveras plus de documentation dessus ici http://laravel.com/docs/4.2/eloquent#model-events (s'applique aussi a la version 5.1).

<?php
namespace App\Models\Observers;

class DateFinObserver
{
    public function saving($model)
    {
        if (isset($model->date_fin)) {
            $model->state = 'failed';
        }
    }
}

Ici par exemple, au moment de sauvegarder, si une date de fin a été définit, on met la valeur de state a ‘failed’. Le CRON a mon humble avis est overkill. En terme de performance, cette solution est bien plus efficace.

Pour aller plus loin, si tu veux pouvoir differer ce traitement un peu plus tard, le mieux serai d'utiliser les workers. Plus d'info ici http://laravel.com/docs/5.1/queues#writing-job-classes

Bonjour.
Vu que ton champ est de type DATE et non de type DATETIME, il est totalement inutile d'exécuter la tache CRON plusieurs fois par jour, mais une seule fois par jour sera largement suffisant, par exemple tous les jours à 00:05.
Le faire plusieurs fois par jours, ne fera que faire des requêtes SQL totalement inutile, sauf pour la première bien sûr.
Quel est l'intérêt d'augmenter la charge du serveur pour des opérations supplémentaires dans ton cas inutile ?

Benares
Auteur

merci pour vos réponses, le problème est que je dois trigger un evenement sans passer par un save ou un update. Clest vraiment quand le date_fin arrive que le status passe a failed (meme si on touche pas l'enregistrement) du coup je pense que cron serai plus adapté

PS : mes champs sont bien des DATETIME =) (une petite erreur de ma part =) )

Merci quand meme pour l'exemple des observers ca me servira dans une autre partie ^^

Hello kal-el,

J'avais déjà entendu parler de l'Observer, mais jamais utilisé. En effet, c'est assez utile. Mais dans son cas, la date est enregistré au préalable, donc le système d'Observer n'est pas utile ici je me trompe ? Etant donné que la donné n'est pas modifié, et bien les méthodes de l'Observer ne sont pas lancé ?
Je m'explique :
Enregistrement le 15/11/2015 :
id => 1
date_fin => 01/12/2015
status => pending

Si aucune modification n'a lieu sur cet enregistrement après le 01/12, alors rien ne se passera ?

@PallMallShow, effectivement, je n'avais pas compris la question sous cette angle la. Du coup, le CRON est bien adapté a ce type de cas. A voir pour la fréquence comme le dit @Lartak.