Bonjour à tous,
Je sais bien qu'il y a eu de nombreux postes à ce sujet, mais je ne comprends pas bien les démarches à appliquer pour integrer et faire fonctionner le sdk php de facebook avec cakephp, pour moi, la version 2.6.2.
J'ai manuellement placer le SDK dans app/Vendor, ce qui me donne :
app/Vendor/facebook/php-sdk-v4/src, mais malgré la video tuto sur l'utilisation en general de ce sdk, je ne comprends pas comment l'utiliser dans cakephp et quelles sont les impératifs pour le rendre fonctionnel, avant meme de vouloir commencer a utiliser les fonctions qu'ils proposent.
Est-il possible qu'une personne ayant réussie puisse m'aiguiller sur ce sujet?
Merci par avance,

30 réponses


Lartak
Réponse acceptée

Tu peux déjà commencer par regarder ce tutoriel : CakePHP » Facebook Connect, il n'est pas très récent, mais tu sauras déjà comment t'y prendre pour utiliser une librairie/API externe, si tu veux, tu peux aussi t'inspirer d'un plugin qui est sur Github, qui n'est pas spécialement récent, mais qui à ma connaissance est toujours fonctionnel : Webtechnick » CakePHP-Facebook-Plugin.
Avec ces deux sources d'informations et de support (qui de plus sont spécifiques, surtout pour le second à CakePHP), tu devrais pouvoir t'en sortir.

Lartak
Réponse acceptée

Ce n'est pas parce que tu demande à récupérer l'email de l'utilisateur dans la méthode login du helper Facebook, qu'il va l'enregistrer lors de la création de l'utilisateur, comme tu peux le voir, il n'enregistre que le facebook_id et le password qu'il génère, pour passer l'authentification.
Le $this->uid correspond au facebook_id et ce n'est pas la peine d'essayer de faire un debug sur autre chose, étant donné qu'il n'y a que le facebook_id d'accessible à cette étape.
Les seules données supplémentaires qu'il peut sauvegarder, sont celles que tu lui définis dans le callback, mais il ne suffit pas de lui donner des noms de champs, il faut aussi définir les valeurs.
Si ce sont des données auxquelles tu as accès avec $this->Connect->user(), il te faut le définir avec, sinon, il te faut le définir toi même.
Si par exemple tu veux qu'il ajoute l'ip de l'utilisateur, dans le callback, il te faut mettre quelque chose du genre :

public function beforeFacebookSave(){
    $this->Connect->authUser['User']['email'] = $this->Connect->user('email');
    $this->Connect->authUser['User']['register_ip'] = $this->request->clientIp();
    return true;
}

De cette manière, lors de l'enregistrement d'un utilisateur, il ajoutera l'adresse email et l'adresse IP de l'utilisateur lors de la création de l'enregistrement.

m'indique que je demande les infos publics et la liste d'amis

C'est normal, c'est le minimum d'informations qu'il affiche à l'utilisateur car c'est ce que Facebook à besoin pour l'API.

Bonsoir.
Tu es sur la V2 de CakePHP ?
Il ne te faut pas oublier de le charger quand tu veux l'utiliser et que veux tu dire exactement par : Quels sont les impératifs ?
Normalement, les principaux impératifs pour l'utiliser sont définis dans la doc du sdk de Facebook.

Bonsoir Lartak,
he bien j'entends par impératifs, la manière de l'intégrer a cakephp ( oui la vesion 2.6.2) et les premières manip pour le charger.
Parceque jusqu'a présent je me suis contenté de décompresser le sdk de facebook dans le dossier Vendor de cakephp, et, surement maladroitement, d'essayer des appels des fonctions liés au sdk en plaçant des app::use et des use:: dans mon Appcontroller et mon UserController.

Alors j'ai bien suivis les indications du tuto sur le facebook connect, j'arrive à presque tout faire fonctionner, à l'exception du fait ma session ne reste pas active.
C'est à dire, qu'apres avoir pris les infos fb en base de données, le Auth->login ne passe pas bien d'un part, et une fois les infos en BDD, il ne passe plus dans le if($this->User->save j'essaie donc de le auth dans le else avec un try catch, et à a ce moment plusieurs choses :
Premierement, une erreur avec la view facebook.ctp ( ce qui est normal je ne l'ai pas faite) mais ca pas grave.
Deuxiement, ma session est bien apparu quand je debug la session->read() au debut du default.ctp, mais des que je change de page, la session reviens a null, et je ne comprends pas du tout comment ça se fait :s
Il semblerai qu'apres les redirect qui ont lieu apres les Auth->login, le contenu des sessions et meme des tableau $u et $use soit vidé. Lors d'un debug avant le redirect je vois bien le contenu de mes tableaux, et apres le redirect, les tableaux sont à 'null'
je met mon code de la fonction facebook pour voir si vous trouvez qqch :

//UserController.php

//LOGIN AVEC FACEBOOK
    public function facebook(){
        require APPLIBS.'Facebook'.DS.'facebook.php';
        $facebook = new Facebook(array(
            'appId' => '14564567868405159',
            'secret' => '****************************'
        ));
        $user = $facebook->getUser();
        if($user){
            try{
                $infos = $facebook->api('/me');
                $d = array(
                    'username' => $infos['name'],
                    'email' => $infos['email'],
                    'facebook_uid' => $infos['id']
                );
                if($this->User->save($d)){
                    $u = $this->User->read();
                    $this->Auth->login($u['User']);
                    //$this->Session->setFlash("Cangrats ! Vous êtes maintenant inscrit.");
                    //$this->redirect(array("controller"=>"quotes", "action"=>"index"));
                    debug($u);
                    //$this->Auth->login($u['User']);
                }else{
                    try{
                        $use = $this->User->find('first', array(
                            'recursive' => -1,
                            'conditions' => array('facebook_uid' => $infos['id'])
                        ));
                        $this->Auth->login($use['User']);
                    }catch(Exception $o){
                        $this->Session->setFlash("L'enregistrement de vos informations ont echoué, votre adresse email est peut-être déjà enregistrée.");
                    }
                }
                $d = array();
            }catch(FacebookApiException $e){
                $this->Session->setFlash("Une erreur est survenue lors de la connexion avec facebook a échoué.");
                $this->redirect(array('action'=>'login'));
            }
        }else{
                $this->Session->setFlash("La connexion avec facebook a échoué.");
                $this->redirect(array('action'=>'login'));
        }

    }

Alors, j'ai trouvé quelques éléments de réponse, mais qui ne semble pas fonctionner :/
Premiere solution, mais je ne comprends pas vraiment, je ne vois pas ce que je dois faire.
Deuxieme solution, mais là ca ne marche pas, la perte de session persiste apres un changement de page.
Et le probleme n'apparait que lorsque je me log avec facebook.

Bonjour.
Pour commencer, lorsque l'on utilise la méthode read, il faut lui définir l'id de l'enregistrement voulu, comme ceci par exemple :

$this->User->id = $id;
$user = $this->User->read();

Dans ton cas, il faut donc par exemple que tu fasse :

if ($use = $this->User->save($d)) {
    $this->User->id = $use['User']['id']);
    $use = $this->User->read();
    /* etc... */
}

Ou :

if ($use = $this->User->save($d)) {
    $use = $this->User->read(null, $use['User']['id']);
    /* etc... */
}

Ensuite, si tu veux faire un debug dans une vue, fais le de préférence dans une vue normale et non dans le layout, ou alors, au moins après le :

<?= $this->fetch('content') ?>

Bonjour et merci Lartak pour ces indications, je les ais appliquées, et j'ai créé ma vue facebook.ctp pour debuger la session->read() dedans.
Cependant le probleme de perte session apres un changement de page ou une redirection persite toujours. Je réaffiche le code au cas ou j'aurai commis une nouvelle erreur.
Y a t il un moyen supplémentaire (autre du debug) pour savoir d'ou proviendrait cette "erreur" ou du moins perte de session ?

$user = $facebook->getUser();
        if($user){
            try{
                $infos = $facebook->api('/me');
                $d = array(
                    'username' => $infos['name'],
                    'email' => $infos['email'],
                    'facebook_uid' => $infos['id']
                );
                if($this->User->save($d)){
                    $id = $this->User->id;
                    $u = $this->User->read(null, $id);
                    $this->Auth->login($u['User']);
                    $this->Session->setFlash('Tu es maintenant inscrit.');
                }else{
                    try{
                        $use = $this->User->find('first', array(
                            'recursive' => -1,
                            'conditions' => array('facebook_uid' => $infos['id'])
                        ));
                        $this->User->id = $use['User']['id'];
                        $loguser = $this->User->read(null, $use['User']['id']);
                        $this->Auth->login();
                        $this->Session->setFlash("Tu es connecté.");
                    }catch(Exception $o){
                        $this->Session->setFlash("L'enregistrement de vos informations a echoué, votre adresse email est peut-être déjà enregistrée.");
                    }
                }
                $d = array();
            }catch(FacebookApiException $e){
                $this->Session->setFlash("Une erreur est survenue lors de la connexion avec facebook a échoué.");
                $this->redirect(array('action'=>'login'));
            }
        }else{
                $this->Session->setFlash("La connexion avec facebook a échoué.");
                $this->redirect(array('action'=>'login'));
        }

je pense que le plugincne dout plus etre fonctionnel, car le sdk de facebook et rendu a la version 4. je vais essayer de le mettre en place sur mon site. Cela m'a cause bien des problèmes entre la version 2 et le sdk de facebook.

Merci Lartak pour ce plugin.

Si tu veux dire que dans le code que tu montres, que tu utilises le plugin Facebook de Webtechnick, je ne crois pas non.
Car je l'ai testé (une fois de plus), il n' y a même pas 2 mois et il était fonctionnel, surtout qu'avec le plugin que j'ai mentionné, il n'y a pas à s'occuper des parties de connexion et inscription de l'utilisateur, tu peux par contre étendre le plugin, si tu veux par exemple récupérer/enregistrer des données supplémentaires, que ce soit pour la connexion et/ou l'inscription.
Lors de la connexion de l'utilisateur, le plugin vérifie si un utilisateur existe déjà avec l'id Facebook de l'utilisateur (à condition d'avoir ajouté un champ (Facebook_id) bien sûr.
Si c'est le cas, il ne fait que connecter l'utilisateur, sinon, il crée un nouvel enregistrement avec un mot de passe généré et le connecte.

Je crois que musicalitymaker parle du sdk que j'utilise, celui qui est presenté dans la video tuto de grafikart sur facebookconnect.
Mais mise à part ce soucis de session, tout semble bioen fonctionner.

Oups, désolé, j'ai répondu un peu trop à la va-vite, du coup, je n'avais pas remarqué que ce n'était pas toi Frank Drebin qui avait posté juste avant.
Mais ça ne change rien au fait, que le plugin de Webtechnick est logiquement toujours fonctionnel (pour la V2 de CakePHP bien sûr, mais pas pour la V3).
Tu peux essayer en écrivant manuellement dans la session :


$this->Session->write('Auth.User', $u['User']);

He bien j'ai essayé d'écrire dans la session apres le Auth->login, avant, à la place mais rien n'y fait.
D'apres ce que je lis dans les resu google, ça serait à cause des header('Location, mais je ne comprends pas bien.
Je crois que c'est expliqué ici.
Peut-être devrai-je changer de solution, le plugin que tu m'a indiquer me permet de faire un log avec les utilisateurs facebook ?

Qu'appelles-tu faire un log ?
Concernant la connexion/inscription, il connecte l'utilisateur qui est déjà enregistré en BDD avec son id Facebook, pour ceux qui ne sont pas inscrit en BDD ou qui n'ont pas leur id Facebook en BDD (et écrit en session les infos Facebook de l'utilisateur récupérées), il crée l'enregistrement et connecte l'utilisateur.
Après, si tu veux faire quelque chose après la connexion et/ou l'inscription, il te faut le faire toi même, regardes sur GitHub, le plugin est relativement bien expliqué.

Ha oui pardon je me suis mal exprimé, je voulais dire se connecté, se login;
En gros le plugin que tu m'as indiqué fait ce que fait le sdk php que j'utilise ici et qui est présenté dans la video facebook connect de grafikart?
Je vais aller y jeter un oeil ^^ si tu me dis que tu as, à plusieurs reprise réussi à l'utiliser correctement. ^^
En tout cas merci encore pr le temps que tu passe à m'aider .

Oui, il effectue la connexion (login) / l'inscription de l'utilisateur et le plugin est relativement simple à utiliser et suffisamment documenté.
Il contient également des helpers pour interagir avec Facebook, tu le verras en regardant sur GitHub.

Oki trés bien, je l'installe actuellement. Petites questions d'avant demarrage, je dois rentrer appId, appKey et le secret, mais pour etre sur, apikey c est la meme chose que l'appId ?

Et une autre petite question, est ce que le plugin pause un soucis avec les regles de validations des formulaires de connexions ? c'est à dire que si je suis par exemple en username isUnique et alphanumeric, si jms j'ai un enregistrement via facebook avec un nom comportant un espace ou apostrophe ca me pausera probleme ? Où si j'ai deux utilisateurs avec même nom et meme prénom ?

Non, ce qui correspond à apiKey, c'est le Client Token que tu trouves dans : Settings » Advanced » Security.

D'acc merci.
Donc soit je m'y suis mal pris soit c'est lié au sdk que j'utilisais avant, mais a chaque refresh de ma page il me connect avec mon id facebook et il y a une session de lancé avec mo id facebook et les autres infos vides, null ou avec les valeur par défaut de la base.
Je détaille rapidement ce que j'ai fait pr installer le plugin au cas ou il y aitune erreur à ce niveau.
-> Téléchargement du plugin dans dossier de téléchargement.
-> Décompression dans ce dossier.
-> Copier/Coller du contenu du dossier c'est a dire (Config, controller, Lib.....) dans le répertoire : app/plugin/Facebook/
-> Dans app/Config/bootstrap.php => CakePlugin::load('Facebook');
-> Renomer app/Plugin/Facebook/Config/facebook.php.example en .../facebook.php
-> Remplissage des infos appId... dans ce fichier facebook.php
-> Copier/Coller ce fichier (facebook.php) dans app/Config
-> Dans le layout default.ctp remplacement de la balise </DOCTYPE html> par <?php echo $this->Facebook->html(); ?> et avant la fermeture de la basilse html ajout de <?php echo $this->Facebook->init(); ?>
-> Dans app/Controller/appController.php ajout du helpers
-> Enfin dans app/Controller/AppController.php ajout des components nécessaires, ce qui donne :

class AppController extends Controller {
    public $helpers = array('Html', 'Form', 'Session', 'Facebook.Facebook');

    public $components = array(
        'Cookie',
        'RequestHandler',
        'Session',
        'Auth' => array(
            'authenticate' => array(
                'Form' => array(
                    'fields' => array('username' => 'email')
                )
            ),
            'authorize' => 'Controller'
        ),
        'Facebook.Connect' => array('model' => 'User')
    );

Je ne crois pourtant pas avoir commis d'erreur ?

Quand il crée un enregistrement, il ne rempli que les champs password et facebook_id, il ne peut pas deviner ce que tu veux enregistrer comme données.
Il y a un callback pour lui faire ajouter des données lors de l'ajout d'un enregistrement et un autre pour la connexion.
Les callback pour l'authentification sont ici : Facebook Auth Callbacks.

Oui en effet, j'ai un peu de mal :s Que je dise pas de bétises, les callback je les placent dans AppController.php pas dans le UserController.php ?
Et c'est bien normal que tant qu'ils ne sont pas en place je ne puis pas me connecter avec un compte déja crée sans facebook ?

Normalement c'est dans ton controller Users que tu dois mettre tes callbacks, si ton modèle relié à l'authentification des utilisateurs est User.
Le composant fait une recherche sur le champ facebook_id, donc s'il ne trouve pas l'identifiant correspondant à l'utilisateur qui se connecte, il créera forcément un nouvel enregistrement.

$this->authUser = $this->User->findByFacebookId($this->uid);

Plugin » Facebook » Controller » Component » ConnectComponent.php » ligne : 156

// attempt to find the user by their facebook id
            $this->authUser = $this->User->findByFacebookId($this->uid);
            //if we have a user, set hasAccount
            if(!empty($this->authUser)){
                $this->hasAccount = true;
            }
            //create the user if we don't have one
            elseif(empty($this->authUser) && $this->createUser) {
                $this->authUser[$this->User->alias]['facebook_id'] = $this->uid;
                $this->authUser[$this->User->alias][$this->modelFields['password']] = Security::hash(FacebookInfo::randPass());
                if($this->__runCallback('beforeFacebookSave')){
                    $this->hasAccount = ($this->User->save($this->authUser, array('validate' => false)));
                }
                else {
                    $this->authUser = null;
                }

Alala je suis vraiement désolé hein mais j'y arrive vraiement pas, même en fouillant un peu dans le plugin pr comprendre comment il fonctionne.
J'ai bien placer mes callback dans UserController.php cepenadnt même avec un die(); dans le beforefacebookSave il me renvoie vers l'erreur :

Missing Controller

Error: CakephpController could not be found.

Error: Create the class CakephpController below in file: app/Controller/CakephpController.php

<?php
class CakephpController extends AppController {

}

Notice: If you want to customize this error message, create app/View/Errors/missing_controller.ctp

Mais seulement lorsque j'utilise le Formulaire de registration.( je prefere avoir juste le bouton de connexion).
Mais plusieurs petites choses du coup que je ne pense avoir bien comprise.
Deja que j'utilise le form registration ou le bouton de connexion l'enregisrtement est crée en base de donnée alors je place un return flase; dans le beforeFacebookSave;
Et surtout, je ne peux plus me connecter avec mes login password des autres utilisateurs deja enregistrer, un mauvais password ou login est indiqué.( avec le systeme classique "Auth->login" de cakephp)

Pourquoi tu mets un return false; dans le beforeFacebookSave ?
Il n'a rien avoir avec le Registration Form.

Le Registration Form, tu l'utilises en dehors de la phase de connexion et d'inscription du plugin.

J'avais compris qu'il faisait l'enregistration en bdd seulement avec le registration et que la connexion pr le login, mais je viens de saisir en effet que ca n'etait pas du tout ca.
Le return false c'était pour tester le passage dans la fonction beforeFacebookSave j'avais mal regarder dans le plugin je pensais qu'il en faisait pas de save->data avant de passer dans le beforeFacebookSave.
Malgré tout, apres une premiere connexion et donc un utilisateur en base de créé, il continu de me créé des utilisateurs avec le même facebook id j'ai pourtant l'impression que le test ce fait sur ce champs. Par contre je ne vois pas ou rajouter les autres champs en plus du password et du facebook_id.
Je pensais eventuellement dans le beforeFacebookSave justement ou alors juste avant son appel, dans le
Plugin » Facebook » Controller » Component » ConnectComponent.php

Et le echo $this->Facebook->login(array('perms' => 'email')); s'affiche seulement de temps en temps .
Je constate aussi que la permission pour l'email n'est pas demandé :s

Le callback beforeFacebookSave permet bien d'ajouter des données avant l'enregistrement d'un nouvel utilisateur, mais tu ne dois pas l'utiliser pour annuler l'enregistrement ou alors à la rigueur pendant tes test, pour faire un debug des données qu'il va enregistrer, mais dans ce cas là, mets un die() juste après le debug.
Les données à récupérer pour faire un update dans l'enregistrement d'un utilisateur avec le Registration Form et le registrationData, n'a aucun impact sur le callback beforeFacebookSave, il te faut traiter les données du formulaire et la sauvegarde, dans une fonction à part.
Par exemple :

public function facebook(){
    if($user = $this->Connect->registrationData()){
        $this->User->save($user);
        return $this->redirect('/');
    }
}

C'est juste un exemple, il te faut faire des tests pour voir exactement comment ça fonctionne. :)

D'accord je vois, de toute manière passer par le registation form et data n est pas necessaire d'apres ce que je comprends puis qu'il crée aussi un nouvelle utilisateur en passant par le bouton de connexion si celui ci nest pas deja en base de données et il fait le test sur le facebook id pr savoir s'il y est (j'espère ne pas me tromper).
En outre, un die(); dans le beforeFacebooksave ne semble pas altérer la création d'nu nouvelle utilisateur sur ma configuration en tout cas :s (je referais des test pr confirmer ça). De même que les debug que je fais a cet endroit (suivit d'un die('beforeFacebookSave');) n'affiche rien le process continue :/.

Sinon j'arrive maintenant à me connecter avec le systeme de cakephp en meme temps que j'ai le plugin lancé.
C'etait du au fait que 'authenticate form fields place username => email comme suivant :

'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email')
)
j'ai donc remplacer email par username. Mais j'ai bien peur que ca puisse gener la connexion avec facebook non ?

Re, alors je viens d'effectuer des tests, dans :
*Plugin » Facebook » Controller » Component » ConnectComponent.php » commence ligne 160 a peu prés

elseif(empty($this->authUser) && $this->createUser) {
                debug($this->authUser);
                debug($this->createUser);
                die('ComponentFacebook');
                $this->authUser[$this->User->alias]['facebook_id'] = $this->uid;
                $this->authUser[$this->User->alias][$this->modelFields['password']] = Security::hash(FacebookInfo::randPass());
                if($this->__runCallback('beforeFacebookSave')){
                    $this->hasAccount = ($this->User->save($this->authUser, array('validate' => false)));
                }
                else {
                    $this->authUser = null;
                }

le premier $this->authUser me renvoie un tableau vide : array()
et le second debug me retourne true.
il semblerai qu'il y ai un soucis au niveau de la récupération des données.
Le popup de connexion facebook m'inque aussi que je dois metre à jour l'app; message :
You must upgrade this app to Graph API v2.x
v1.0 will be deprecated on April 30, 2015

Il est tout à fait normal que le $this->authUser renvoi un tableau vide, puisque tu es dans la boucle conditionnelle dans le cas ou $this->authUser est vide et le $this->createUser, ne récupère pas d'infos, il ne renvoi que true ou false.
Ligne 47 à 52

    /**
    * createUser is true you want the component to attempt to create a CakePHP Auth user
    * account by introspection on the Auth component.  If false, you can use $this->hasAccount
    * as a reference to decide what to do with that user. (default true)
    */
    public $createUser = true;

C'est avant le :

if($this->__runCallback('beforeFacebookSave')){

que tu peux vérifier les données qui seront enregistrées en BDD (avec $this->authUser), ou après si tu définis des données à enregistrer en base de données dans le callback.

Le popup de connexion facebook m'inque aussi que je dois metre à jour l'app

Il te dit que l'API que tu utilises sera dépréciée dans 1 mois.
Après tout, Facebook est en constante évolution et il est normal que l'API aussi évolue elle aussi et le plugin a quand même été modifié il y a un bon moment, la dernière modification a été faite il y a à peu près 6 mois.

Yep oui en effet j'avais compris ça, mais été un peu précipité sur mon poste. Je voulais dire que ne savais pas comment et ou trouver les information à entrer dans la bdd, seul $this->uid me retourne qqch.

elseif(empty($this->authUser) && $this->createUser) {
                debug($this->data);
                debug($this->uid);
                debug($this->email);

                $this->authUser[$this->User->alias]['facebook_id'] = $this->uid;
                $this->authUser[$this->User->alias][$this->modelFields['password']] = Security::hash(FacebookInfo::randPass());
                debug($this->authUser);
                                die('create the user if we don\'t have one');
                if($this->__runCallback('beforeFacebookSave')){
                    $this->hasAccount = ($this->User->save($this->authUser, array('validate' => false)));
                }
                else {

mise à part ce qu'il y a apres l'affectation a authUser, les 3 debug me retourne null à l'exception de uid.
De plus, le popup de connexion faebook m'indique que je demande les infos publics et la liste d'amis (que je ne demande pas) en revanche je demande le email en perms du Facebook->login mais il n'y apparait pas.