Bonjour,
je travaille sur un projet de systeme de membre ou chaque personne peut s'inscrire en telechargeant ou pas un avatar pour son profil,
ce n'est pas obligatoire de mettre une image. Et une fois le profil crée, chaque membre peut editer son profil donc telecharger une nouvelle image ou changer celle téléchargée à l'inscription.
J'ai une fonction edit pour telecharger un avatar mais j'y arrive pas et le champs affiche obligatoire alors que je veux que ce ne soit qu'une possiblité.
C'est la première fois que je travaille avec CakePHP et je suis un peu perdue.
Merci d'avance de votre aide

Ce que je fais

Voila ce jai dans ma fonction edit dans UsersController

        if(!empty($this->request->data)){
            $this->request->data['User']['id'] = 1;
            $this->User->save($this->request->data);

        }else{
            $this->User->id = 1;
            $this->request->data = $this->User->read();
        }

Voila ce que j'ai dans mon model, la fonction fileExtensions et la fonction aftershave

        $file = current($check);
        if($allowEmpty && empty($file['tmp_name'])){
            return true;
        }
        $extension = strtolower(pathinfo($file['name'] , PATHINFO_EXTENSION));
        return in_array($extension, $extensions);
    }

    public function afterSave($created){
        if(isset($this->data[$this->alias]['avatar_file'])){
            $file = $this->data[$this->alias]['avatar_file'];
            $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
            if(!empty($file['tmp_name'])){
                $oldextension = $this->field('avatar');
                $oldfile = IMAGES . 'avatars' . DS . $this->id . '.' . $oldextension
                ;
                if(file_exists($oldfile)){
                    unlink($oldfile);
                }
                move_uploaded_file(
                    $file['tmp_name'],
                    IMAGES . 'avatars' . DS . $this->id . '.' . $extension
                );
                $this->saveField('avatar', $extension);
            }
        }
    }

Ce que je veux

Je veux pouvoir telecharger un avatar l'enregistrer dans le dossier avatar dans img et l'afficher dans mon profil.

Ce que j'obtiens

J'obtiens l'erreur
Declaration of User::afterSave() should be compatible with Model::afterSave($created, $options = Array) [APP\Model\User.php, line 7]
De plus, l'image ne s'enregistre pas dans le dossier et le profil ne s'edite pas.
Le champs avatar s'affiche avec une * rouge obligeant le membre à mettre un avatar.

13 réponses


Bonjour.
Pour l'erreur :

Declaration of User::afterSave() should be compatible with Model::afterSave($created, $options = Array) [APP\Model\User.php, line 7]

Il te suffit tout simplement de modifier :

public function afterSave($created){

Par :

public function afterSave($created, $options = array()){

Je ne sais pas quelle version de CakePHP tu utilises, mais depuis la 2.4 la constante IMAGES est obsolète.

Hassan
Auteur

Merci de ton aide! J'ai corrigé l'erreur. je suis sur cakePHP 2.6 jai changer la constante IMAGES mais ca fonctionne toujours pas.

Bonjour.

Le champs avatar s'affiche avec une * rouge obligeant le membre à mettre un avatar.

Montres nous la règle de validation concernant ton champ avatar_file.

Le champs avatar s'affiche avec une * rouge obligeant le membre à mettre un avatar.

Étant donné que la soumission du formulaire retourne une erreur lors du passage de la validation, la sauvegarde ne s'effectue pas, donc pas de modification en base de données et par conséquent le callback afterSave ne s'effectue pas et donc pas de déplacement/copie de l'image.

Hassan
Auteur

Voici la règle de validation pour avatar_file

                    'rule'    => array('fileExtension', array('gif', 'jpeg', 'png', 'jpg')),
                    'message' => 'Merci de soumettre une image valide.',
            ),

Pour information (au passage), il t'est inutile de créer une règle personnalisée pour vérifier l'extension de fichier dans les règles de validation, il y en a déjà une d'incluse dans CakePHP : Règles de validation incluses » Validation::extension.
Je te conseille donc d'utiliser la règle de validation existante, par exemple :

'avatar_file' => array(
    'rule' => array('extension', array('gif', 'jpeg', 'png', 'jpg')), 
    'required' => false, 
    'allowEmpty' => true, 
    'message'    => 'Merci de soumettre une image valide.'
)
Hassan
Auteur

Merci beaucoup pour ta réponse et surtout pour l'information. Le champs avatar n'a plus le * rouge, mais je n'arrive toujours pas à éditer mon profil, le champs email affiche l'erreur 'Ce mail est déjà pris', pourtant je n'ai pas touché à l'email.

Est-ce qu'il y a le champ pour l'email dans le formulaire d'édition ?

Hassan
Auteur

Oui, il y'a bien le champ email:

                    array('label' => 'Mail</td><td>',
Hassan
Auteur

Et voila la règle de validation pour mail:

'mail' => array(
            array(
                'rule' => 'email',
                //'required' => 'create',
                'allowEmpty' => false,
                'message' => 'Votre mail n\'est pas valide'
            ),
            array(
                'rule' => 'isUnique',
                'message' => 'Ce mail est déjà pris'
            ),

Pour commencer, ton format pour le multi-règles par champ n'est pas correct, il doit se présenter comme-ceci :

'champ' => array(
    'regle1' => array(
        'rule' => '...',
        ...
    ),
    'regle2' => array(
        'rule' => '...', 
        ...
    )
)

Le fait de donner un nom à une règle dans le cas de multi-règles pour un champ, te permet dans un premier temps de reconnaître/trouver plus rapidement une règle et dans un deuxième temps de pouvoir manipuler ces règles depuis le controller (comme par exemple désactiver/modifier l'une de ces règles à la volée depuis les controlleurs).
Donc pour ton cas par exemple :

'mail' => array(
    'format' => array(
        'rule' => 'email', 
        'allowEmpty' => false, 
        'message' => 'Votre mail n\'est pas valide'
    ), 
    'unique' => array(
        'rule' => 'isUnique', 
        'message' => 'Ce mail est déjà pris'
    )
)

pourtant je n'ai pas touché à l'email

Que veux-tu dire précisément ?
Que l'email s'affiche dans l'input du formulaire et que tu ne l'as pas modifié ?
Dans tous les cas, vérifies que tu n'as pas l'adresse email liée au compte édité déjà présent dans un autre enregistrement de ta table, car si par exemple tu as ajouté cette règle après avoir créé des enregistrements et que l'email est déjà présent dans un autre enregistrement, tu n'auras pas eu l'erreur lors de la création des enregistrements, mais maintenant qu'il y a la règle il va systématiquement faire la vérification lors des sauvegardes.
Et si cet email est présent dans un autre ou d'autres enregistrement(s) que celui du compte édité, c'est tout à fait normal.

Hassan
Auteur

Oui l'email s'affiche dans l'input et je ne l'avais pas modifié. Mais la je l'ai modifié et jai upload un avatar mais le profil ne s'edite toujours pas. J'ai "L'utilisateur n'a pas été editer. Merci de réessayer." et aucun champs n'affiche d'erreur donc je vois pas d'ou je viens le probleme, je crois que c'est dans la fonction edit que se trouve le problème:

        if(!empty($this->request->data)){
            $this->request->data['User']['id'] = 1;
            $this->User->save($this->request->data);
            $extension = strtolower(pathinfo($this->request->data['User']['avatar_file']['name'], PATHINFO_EXTENSION));
            if(!empty($this->request->data['User']['avatar_file']['tmp_name']) && in_array($extension, array('png','jpg','jpeg','gif'))
            ){
                move_uploaded_file(
                    $this->request->data['User']['avatar_file']['tmp_name'],
                    WWW_ROOT.'img' . DS . 'avatars' . DS . $this->id . '.' . $extension
                );
                $this->User->saveField('avatar', $extension);
               }
                else if(!empty($this->request->data['User']['avatar_file']['tmp_name'])
                ){
                    $this->Session->setFlash("Vous ne pouvez pas télécharger ce type de fichier");
            }
        }else{
            $this->User->id = 1;
            $this->request->data = $this->User->read();
        }
 if (! $user = $this->User->findById($id)) {
            throw new NotFoundException(__('Utilisateur Invalide'));
        }
        if ( $this->request->is('put')) {

            if ($this->User->save($this->request->data)) {
                $this->Session->setFlash('L\'utilisateur a été édité','default', array('class' => 'alert alert-success'));
             if($this->Auth->user('id') == $id)
                 $this->Auth->login($this->request->data['User']);
                return $this->redirect(array('action' => 'index'));
            } else {
                $this->Session->setFlash('L\'utilisateur n\'a pas été édité. Merci de réessayer.','default', array('class' => 'alert alert-danger'));
            }
        } else {
            $this->request->data = $user;
            unset($this->request->data['User']['password']);
        }
    }

Si le code que tu donnes ne fait bien parti que d'une seule fonction, il y a un problème, tu fais deux traitements différents des requêtes de formulaire :

if(!empty($this->request->data)){

Et :

if ( $this->request->is('put')) {

Étant donné que tu ne fais pas de redirection après le premier traitement, le second s'effectue également.
Ensuite, pourquoi est-ce que tu fais le traitement pour l'image dans la fonction du controller alors que tu en a déjà un dans le modèle ?
Un conseil, lorsque tu es en phase de développement, fais par exemple des debug au fur et à mesure des étapes de traitement, ce qui te permettra de situer l'origine des problèmes.
Qu'est-ce que c'est cette partie ?

else if(!empty($this->request->data['User']['avatar_file']['tmp_name'])) {
    $this->Session->setFlash("Vous ne pouvez pas télécharger ce type de fichier");
}

Ce n'est pas logique, je ne vois pas le rapport entre la condition et le message d'erreur, surtout que tu as les règles de validations de ton modèle qui sont là pour retourner ce genre de message d'erreur.
Autre chose, ton champ en base de données, il se nomme avatar ou avatar_file ?
Car si lorsque tu fais une sauvegarde en base de données tu envoies avatar_file alors que ton champ se nomme avatar (ou inversement), c'est normal que la sauvegarde échoue.

Je te recommande fortement de visionner ce tutoriel : Tutoriel Vidéo CakePHP » Gérer l'upload de fichiers.

Hassan
Auteur

Merci beaucoup de m'avoir éclairer; je vais revoir tout ca. Et revenir si nécessaire.