Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 18-08-2009 11:57:28

MaitreTsiang
Membre
Lieu: Paris
Date d'inscription: 07-08-2007
Messages: 18

Problème de double insertion lors d'un rechargement de la page

Bonjour, je n'ai pas touvé de solution "propre" à mon problème en cherchant dans les forums donc si quelqu'un a "LA" solution parfaite smile

Lorsque j'envoi un formulaire à un controller d'action via la methode 'post' je fais ceci :

function addAction() {
    $post = $this->_request->getPost();
    if($this->db->insert('matable',array(.....)) {
        Si l'insertion a marché je redirige comme ceci:
        $this->_redirect(/controller/autreaction);
    } else {
        sinon ....
    }
}

problème si l'utilisateur rafraichi sa page, l'insertion se fait plusieurs fois.
J'ai vu plusieurs solutions (au niveau de la base de données uniqid,stocké l'objet en session et testé s'il a déjà été passé,...)  tout cela me semble être un peu du bricolage non ?
Comment faites vous avec zend_framework pour éviter cela ?

merci d'avance !

Hors ligne

 

#2 18-08-2009 13:14:16

aelyta1
Membre
Lieu: Rouen
Date d'inscription: 29-06-2009
Messages: 98

Re: Problème de double insertion lors d'un rechargement de la page

Quelle est la page que ton utilisateur rafraichit ? La redirection se fait-elle bien ?

Pour ma part quand je veux récupérer un formulaire je mets une condition

Code:

$request = $this->getRequest();
if($request->isPost())
{
   //traitement et enregistrement des donnees;
}
else{ ..... }

Si ça peut t'aider


veni, vidi, riendi
Vive les lapins-antilopes !

Hors ligne

 

#3 18-08-2009 14:20:08

MaitreTsiang
Membre
Lieu: Paris
Date d'inscription: 07-08-2007
Messages: 18

Re: Problème de double insertion lors d'un rechargement de la page

Oui je fais ça aussi mais si l'utilisateur rafraichi la page ça demande s'il veut renvoyer les données du formulaire ...

Hors ligne

 

#4 18-08-2009 14:40:37

MaitreTsiang
Membre
Lieu: Paris
Date d'inscription: 07-08-2007
Messages: 18

Re: Problème de double insertion lors d'un rechargement de la page

Ok j'ai trouvé, il faut faire le traitement dans une autre action car sinon ça demande de recharger.
En gros le formulaire sur l'action indexAction envoi vers traitementAction qui redirige vers indexAction en cas d'ajout réussi smile

Voilou, si quelqu'un a une solution avec la même action ça peut être intéressant

Dernière modification par MaitreTsiang (18-08-2009 17:39:42)

Hors ligne

 

#5 20-08-2009 22:07:48

lesauf
Membre
Lieu: Yaoundé - Cameroun
Date d'inscription: 29-11-2007
Messages: 52
Site web

Re: Problème de double insertion lors d'un rechargement de la page

C'est la meme solution qu j'utilise (i-e traitement dans une autre action). Ce que je fais c'est que je crée l'objet row avant d'afficher le formulaire, et je le transmet (apres l'avoir serialisé) à l'action de traitement.

Ainsi j'ai

Code:

    /**
     * Prepare un enregistrement pour l'afficher dans le formulaire
     * redirige vers showForm
     * 
     * Cette redirection permet de ne plus faire de requete si le formulaire
     * n'est pas validé
     * 
     * la redirection est effective si $perform est vrai.
     * Pour surcharger cette méthode tout en gardant sont fonctionnement 
     * appeler la methode parente avec $perform à false
     * ajouter les traitements desires puis appeler 
     * $this->_redirect($redirect);
     *        
     * @param boolean $perform
     * @return null
     * @see showForm    
     */
    public function addAction($perform = true) 
    {
        $this->session->saveMethod = 'add';
        
        // création de l'objet row
        $rowObject = $this->model->newRow();
        $data = $rowObject->toArray();

        // menregistrement de l'objet row en session
        $this->session->rowObject = serialize($rowObject);
        // données du formulaire
        $this->session->formData = $data;

        // Reconduction des messages
        $messages = $this->_flashMessenger->getMessages();
        foreach ($messages as $message) {
            $this->_flashMessenger->addMessage($message);
        }
        // Message formulaire
        $this->_flashMessenger->addMessage(
                                    $this->_messages['formFieldRequired']);

        $redirect = $this->_to('process-form');

        if ($perform) {
            $this->_redirect($redirect);
        } else {
            return $redirect;
        }
    }

    /**
     * Recherche l'enregistrement pour l'afficher dans le formulaire
     * redirige vers showForm
     * 
     * Cette redirection permet de ne plus faire de requete si le formulaire
     * n'est pas validé
     * 
     * la redirection est effective si $perform est vrai.
     * Pour surcharger cette methode tout en gardant sont fonctionnement 
     * appeler la methode parente avec $perform à false    * ajouter les 
     *  traitements desires puis appeler 
     * $this->_redirect($redirect);
     *        
     * @param boolean $perform
     * @return null
     * @see showForm    
     */
    public function editAction($perform = true) 
    {
        $this->session->saveMethod = 'edit';
        $id = $this->_request->get('id');
        
        // création du row
        $rowObject = $this->model->fetchRow($id);
        $data = $rowObject->toArray();

        if (!$data) {
            // Si aucune donnée, rediriger vers la liste
            $this->_flashMessenger->addMessage(
                            $this->_messages['unknowItem']
                            . $id);
            $redirect = $this->_to('show-list');
        } else {
            // enregistrement du row en session
            $this->session->rowObject = serialize($rowObject);
            // données du formulaire
            $this->session->formData = $data;

            // Message du formulaire
            $this->_flashMessenger->addMessage(
                                    $this->_messages['formFieldRequired']);

            $redirect = $this->_to('process-form');
        }
        
        // redirection
        if ($perform) {
            $this->_redirect($redirect);
        } else {
            return $redirect;
        }
    }

    /**
     * Affiche le formulaire d'edition d'un element.
     *
     * @return null
     */
    public function processFormAction()
    {        
        if (isset($this->session->rowObject)) {
            $this->view->headTitle($this->_titles[$this->session->saveMethod], 'PREPEND');
            $this->view->crud->cancelAction = 'show-list';

            $this->view->crud->cancelButton = $this->_buttons['cancel'];
            $this->view->crud->saveButton   = $this->_buttons['save'];         
            $this->view->formErrors = $this->session->formErrors;

            // validation et enregistrement du formulaire
            if ($this->getRequest()->isPost()) {
                $dataSource = $this->getRequest()->getPost();
                
                // récupération de l'objet row depuis la session
                $rowObject = unserialize($this->session->rowObject);

                // passage des valeurs du formulaire au row
                $rowObject->setFromArray($dataSource);

                /*
                 * vu que l'objet row a été serialisé, il faut le reconnecter
                 * à la bd
                 * Pour cela on lui donne le nom de sa table
                 */
                $rowObject->setTable($this->model->getTable());

                // enregistrement
                try {
                    $pk = $rowObject->save();
                    $this->session->unsetAll();
                    $redirect = $this->_to('view');
                    $this->_redirect($redirect . "/id/$pk");
                } catch (Fast_Form_Exception $e) {
                    // formulaire invalide
                    $form = $rowObject->getForm();
                    
                    // Récupération des messages d'erreur
                    $errors = $form->getMessages();

                    // messages d'erreur
                    $this->_flashMessenger->addMessage(
                                    $this->_messages['invalidFormData']);
                    foreach ($errors as $error) {
                        $error = array("error" => $error[0]);
                        $this->_flashMessenger->addMessage($error);
                    } 
                } catch (Fast_Exception $e) {
                    $this->_flashMessenger->addMessage($this->_messages['unsaved']);
                    // et le formulaire est réaffiché
                }
            } else {
                // Affichage initial du formulaire
                $rowObject = unserialize($this->session->rowObject);

                /*
                 * vu que l'objet row a été serialisé, il faut le reconnecter
                 * à la bd
                 * Pour cela on lui donne le nom de sa table. 
                 * Ceci permet aussi de récupérer le formulaire
                 */
                $rowObject->setTable($this->model->getTable());

                $form = $rowObject->getForm();
            }

            // rendu
            $this->view->form = $form;
        } else {
            // si 
            trigger_error('Invalid context to call show-formAction', 
                                E_USER_WARNING);
            $redirect = $this->_to('show-list');
            $this->session->unsetAll();
            $this->_redirect($redirect);
        }
    }

Je mettrai bientot les fichiers complets en ligne.

Dernière modification par lesauf (20-08-2009 22:12:42)

Hors ligne

 

#6 21-08-2009 09:15:16

MaitreTsiang
Membre
Lieu: Paris
Date d'inscription: 07-08-2007
Messages: 18

Re: Problème de double insertion lors d'un rechargement de la page

Salut, personnellement je ne suis pas un fan du zend_form je trouve cela trop lourd et le code généré ne me plait pas donc je reste à la technique 'old school' smile
Merci pour ta réponse wink

Hors ligne

 

#7 24-08-2009 10:57:41

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Problème de double insertion lors d'un rechargement de la page

bonjour
zf ne le mets pas en œuvre par défaut et les exemples n'en parlent jamais
il existe pourtant un design pattern destiné à ce problème
il s'agit u PRG Post Redirect Get
en clair l'action de ton formulaire en mode post récupère les donnée et le mets en session
puis fait un redirect vers l'action en mode get

si l'utilisateur faut un refresh c'est l'action Get qui est exécuté donc seulement l'affichage du résultat

tu trouvera de la doc sir Wikipédia
et quelques exemples dans ce forum d'utilisation de ce pattern dans ZF

A+JYT

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages