Bonjour à tous :)

Alors voilà j'ai un tableau qui affiche mes posts (j'ai suivi le tuto vidéo de Grafikart) dans un tableau avec les colonnes suivantes : id, titre, date, et j'aimerais que sur cette vue l'utilisateur puisse entrer 2 dates (une de début et une de fin) afin d'afficher que les posts compris entre ces dates. Pourriez vous me donner une ou deux piste à suivre pour parvenir à cela s'il vous plait ? Malgré de nombreuses recherches je n'ai trouvé aucun tuto (anglais ou français) sur le sujet, et mes connaissances en développement ne sont pas assez grandes pour que je m'en sorte tout seul !

ps: si vous souhaitez des précisions ou mon code pour m'aider à partir sur la bonne piste n'hésitez pas :)

Cordialement,

Jango :)

11 réponses


Pakito
Réponse acceptée

Bonjour Jangobtz,

Ce que tu demandes est en fait assez simple à réaliser.

Pour cela, il faut faire un find(). Pour cela, soit tu créés une nouvelle function dans ton controller Posts, du type function recherche_date($date_debut, $date_fin), soit tu ajoutes ces deux paramètres à ta function index en indiquant que par défaut, ils sont à NULL.

Ensuite, dans ton find, il faudra utiliser ces dates si elles ne sont pas à NULL.
Ta fonction pourrait donc ressembler à quelque chose du genre :

public function index($date_debut = null, $date_fin = null) {
    if(!is_null($date_debut) && !is_null($date_fin)):
        $conditions = array(
                'conditions' => array('Post.date BETWEEN '.$date_debut.' AND '.$date_fin)
            );
        $this->set('Posts', $this->Post->find('all', $conditions));
    else :
        $this->set('Posts', $this->Post->find('all'));
    endif;
}

Ici on part du principe que tes Posts ont un champ "date" en base de donnée qui contient leur date de publication. Si ton champ s'appelle différemment, comme created, alors il faut effectuer la recherche sur "Post.created".

Attention : Pour que cela fonctionne si ton champ en BDD est en datetime, il faut que tu passes tes dates de manière à ce que SQL puisse les interprêter pour sa recherche. Pour cela, le format attendu est Ymd. Par exemple pour la date d'aujourd'hui, ce serait "20140414".
Il faut donc que tu passes tes paramètres dans ce format là à ta fonction.

Jangobtz
Auteur

Ah oui effectivement expliqué comme ça ça à l'air simple !

Merci beaucoup d'avoir pris le temps de m'expliquer :) J'avais pas du tout pensé au between dans la requête sql !

et concernant la vue comment je peux faire pour enregistrer ces variables juste temporairement ? Parce que je ne sais pas comment envoyer en POST une donnée autrement qu'avec un formulaire. Or si je fais comme ça il va cherche dans la table de ma BDD les champs non ?

echo $this->Form->create();
echo $this->Form->input('dateDebut');
echo $this->Form->input('dateFin');
echo $this->Form->end();

On peut faire un formulaire qui enregistre juste temporairement les variables dans $dateDebut et $dateFin ?

Tout à fait, tu fais un formulaire qui est présent sur ta vue index, et il s'appellera lui-même.

Cela dit, si tu fais ça en POST, il faudra peut être récupérer les variables via this->request->data. De mémoire, les fonctions ne récupèrent en paramètre que les variables passées en get.

Mais tu peux passer ces éléments en GET aussi, et définir une route pour ça.

Jangobtz
Auteur

Petit souci ! :)

Alors voici mon controleur :

function index($date_debut = null, $date_fin = null){
        if(!is_null($date_debut) && !is_null($date_fin)){
                    $this->paginate = array('Post' => array(
                        'limit' => 4,
                        'order' => array('Post.id' => 'desc'),
                        'conditions' => array('Post.begindate BETWEEN '.$date_debut.' AND '.$date_fin))
                    );
                $d'operations'] = $this->Paginate('Post');  
                $this->set($d);
        }else{
                    $this->paginate = array('Post' => array(
                        'limit' => 4,
                        'order' => array('Post.id' => 'desc'))
                    );
                $d'operations'] = $this->Paginate('Post');  
                $this->set($d);
        }
    }

et ma vue :

echo $this->Form->create(array('type' => 'get'));
echo $this->Form->input('date_debut');
echo $this->Form->input('date_fin');
echo $this->Form->end('Submit');

quand je clique sur submit, mon url devient :

http://adresse\_de\_mon\_site/posts?date\_debut=2014-04-08&date\_fin=2014-04-10

ce qui devrait afficher que celles entre le 8 avril et le 10 avril ! Pourtant ça ne fonctionne pas elles s'affichent quand même toutes .. (j'ai vérifié dans ma bdd les dates s'affichent bien en yyyy-mm-dd) ...

Une idée d'où vient le souci ? à part mon manque de compétence ^^' !

Tes dates en BDD sont en format DATETIME j'imagine ?

C'est ce que je te disais dans mon premier message : SQL ne gère pas les format de la même façon, et il a donc besoin de dates au format yyyymmdd.

Pour que a requête fonctionne, il faut que tu lui passes les dates dans ce format là.

Pour cela, tu peux utiliser nettoyer les dates dans ton controller en ajoutant dans le else (donc si les dates ont été passées) une fonction str_replace sur chacune des deux variables :

$date_debut = str_replace('-', '', $date_debut);
$date_fin = str_replace('-', '', $date_fin);

Voila qui devrait fonctionner !

Jangobtz
Auteur

Oui elles sont en DATETIME :)

dans le else ? Euh j'ai du mal comprendre un truc alors.

!is_null ça veut dire 'différent de null' non ? le '!' veut bien dire différent ?

Donc c'est dans le if que les dates ont été passées non ?

Autant pour moi, je suis fatigué. C'est bien dans le if ;)

Jangobtz
Auteur

Pas de souci :) !

Par contre ça marche toujours pas ...

En mettant les dates comme tu as dis, ça me met une url:

http://adresse\_de\_mon\_site/posts?date\_debut=20140408&date\_fin=20140410 (donc le format que tu m'as dit)

mais ça continue de toutes me les afficher ... ça ne rentre pas dans la boucle :/

Repasse peut-être sur un POST plutôt qu'un GET. Je viens de retrouver un bout de code un peu similaire où j'offre la possibilité dans l'admin sur l'index d'un Model de filtrer les enregistrements affichés.

Et pour cette méthode, je passe le tout en POST.

Je pense donc qu'il suffit que tu créé ton formulaire, en spécifiant uniquement ton Model et l'action index, et que tu créé 2 champs qui ont le nom des variables que tu attends :

echo $this->Form->create('Post', array('url' => array('action' => 'index')));
echo $this->Form->input('date_debut');
echo $this->Form->input('date_fin');
echo $this->Form->end(array('label' => 'Rechercher'));

Ca devrait donc pointer sur ton action Index du controller Posts et passer les variables date_debut et date_fin sans problème.

Jangobtz
Auteur

Désolé du double post mais c'est bon problème réglé :D!!

En fait fallait un $this->request->query('date_debut') et pareil pour date_fin pour récupérer les params passer en GET :D !

Tout le reste est juste !

Merci beaucoup de ton aide Pakito et d'avoir pris le temps de bien m'expliquer !

Y a pas de quoi, c'est un plaisir ;)