Eins vorweg: Die Facebook API ist so mächtig, dass man locker auf der API basierend ein zweites Facebook hochziehen könnte, was durch die Facebook API gespeist wird. Leider gibt es aber auch zich verschiedene Quellen bei Facebook selbst. Vieles, was dort zu finden ist, ist bereits wieder deprecated und sollte nicht mehr verwendet werden. Ich werde nun sowohl die serverseitige (PHP) als auch die clientseitige (Javascript) Kommunikation mit Facebook anhand von Codeschnippseln beschreiben. Dabei verwende ich nur die Techniken, die laut Facebook noch verwendet werden sollten.
Getting Started
Als allererstes muss mal ein API Key her. Das geht hier. Dabei muss ein „App-Name“ vergeben werden und eine Domain spezifiziert werden. Wichtig: Nur Requests, die wirklich von der angegebenen Domain kommen, werden von Facebook zugelassen. Diese Domain kann allerdings jederzeit in eurem Developers-Account geändert werden und auch http://localhost/ geht durch. Dort kriegt ihr auch einen „secret-key“, der ebenfalls wichtig ist.
Serverseite
1) Facebook-Klasse und Zertifikat herunterladen
Auf der Github Seite die facebook.php und das Zertifikat herunterladen. Die Klasse werden wir für die API-Kommunikation brauchen und diese braucht wiederum das Zertikat. Achja, unbedingt CURL in der php.ini aktivieren!
2) Initialisierung
Der Konstruktor der Facebook-Klasse verlangt nach eurer App-ID und dem Secret-Key, den ihr beim Anmelden mitgeteilt bekommen habt.
$facebook = new Facebook(array( 'appId' => 'eure-app-id', 'secret' => 'euer-secret-key', 'cookie' => true ));
Jetzt kanns losgehen!
3) Login-Möglichkeit
Facebook Connect ist ein OAuth-Dienst, der es Benutzern ermöglicht, sich auf eurer Seite über Facebook einzuloggen. Diese melden sich dann mit ihrem Facebook Konto an und gewähren dadurch eurer Webseite Zugriff auf gewisse Daten ihres Profils. Das geht wie folgt:
$url = $facebook->getLoginUrl(array( 'req_perms' => 'email,user_birthday,status_update,user_photos,user_videos,publish_stream', 'next' => 'https://d-mueller.de/thanks.php', 'cancel_url' => 'https://d-mueller.de/sorry.php' )); print '<a href="'.$url.'">Login!</a>';
Ein Klick auf den Login-Link leitet den Benutzer zu facebook weiter, wo er eurer App die Befugnis erteilen kann, seine E-Mail, seinen Geburtstag, seine Statusupdates und seine Fotos / Videos einzusehen. Weiterhin fordern wir noch das Privileg, auch Posts auf die Pinnwand des Nutzers schreiben zu dürfen. Das ist natürlich für ein simples Login völlig übertrieben und verschreckt Benutzer eher. Werden keine req_perms angegeben, ist Zugriff auf die öffentlichen Angaben des Users gestattet. Ist ja eigentlich auch ausreichend. Facebook sagt dazu
By default, your application can access all public data in a user’s profile, including her name, profile picture, gender, and friends
Zur next-URL wird weitergeleitet, nachdem der Benutzer akzeptiert hat. Zur cancel_url, wenn er verweigert hat. Die Angabe beider URLs ist ebenso optional wie req_perms. Sind die URLs nicht gesetzt, wird die Referer-Seite verwendet. Verweigere ich der Applikation den Zugriff werde ich übrigens im obigen Beispiel auf
https://d-mueller.de/sorry.php?perms&selected_profiles=100000415342961
weitergeleitet. Stimme ich zu, lande ich bei
https://d-mueller.de/thanks.php?perms=email,user_birthday,status_update,publish_stream,user_photos,user_videos&selected_profiles=100000415342961&installed=1&session=some-crazy-json-session-information
So lässt sich per
$perms = explode(",",$_GET['perms']);
gut auswerten, welche Rechte der Benutzer der Applikation eingeräumt hat. Dann wird noch die Facebook-Session mit übergeben.
4) Logout-Möglichkeit
$logoutUrl = $facebook->getLogoutUrl(array('next' => 'https://d-mueller.de/loggedout.php'));
Wie oben auch ist die next-URL wieder optional.
5) Alle Infos des Benutzers auslesen, auf die wir Zugriff haben
Habe in Kommentaren unter dem jeweiligen Aufruf den dazugehörigen Output gekleistert.
$session = $facebook->getSession(); if (!$session) { print "Not Logged in or not yet allowed the app!"; print '<a href="'.$facebook->getLoginUrl().'">Login!</a>'; } else { print "Logged in!"; $me = $facebook->api('/me'); print_r($me); /* Array ( [id] => 100000415342961 [name] => David Müller [first_name] => David [last_name] => Müller [link] => http://www.facebook.com/mueller.dav [birthday] => 03/13/1989 [education] => Array ( [0] => Array ( [school] => Array ( [id] => 106191932753089 [name] => HS Darmstadt ) [type] => College ) ) [gender] => male [email] => mueller.dav@gmail.com [timezone] => 1 [locale] => de_DE [verified] => 1 [updated_time] => 2010-11-23T07:01:59+0000 ) */ print_r($session); /* Array ( [session_key] => 2.KNAv1M6c72HwXVjecs8f5g__.3600.1291136400-100000415342961 [uid] => 100000415342961 [expires] => 1291136400 [secret] => dGqYF3hEUpvvVaWZ4T5QAw__ [access_token] => 182175161797277|2.KNAv1M6c72HwXVjecs8f5g__.3600.1291136400-100000415342961|DPZ2h8JmrDlB0_tWs0uMxGgbtK8 [sig] => 82f24e389171741c571bb217874c382b ) */ }
6) Facebook Query Language FQL
Die neue Art, wie die Facebook-API bedient werden sollte ist die FQL. Wer mit SQL einigermaßen vertraut ist, sollte sofort damit klarkommen. Erstmal ein Beispiel:
$fql_query = array( 'method' => 'fql.query', 'query' => 'SELECT uid, first_name, last_name, pic_square, pic_big, sex FROM user WHERE uid = '.$facebook->getUser() ); $fql_info = $facebook->api($fql_query); print_r($fql_info); /* Array ( [0] => Array ( [first_name] => David [last_name] => Müller [pic_big] => http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs168.ash2/41506_100000415342961_8052474_n.jpg [sex] => männlich [uid] => 100000415342961 [pic_square] => http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs169.ash2/41534_100000415342961_1227664_q.jpg ) ) */
Einfach, oder? Hier gibt es eine FQL Referenz mit allen möglichen Feldern und Tabellen, die ihr abfragen könnt. Mit FQL lässt sich so auch herausfinden, welche Berechtigungen ein Benutzer euch erteilt hat. Es ist nämlich nicht gesagt, dass eure App immer gleichviel darf – Ein Benutzer kann nach Belieben die Rechte eurer App einschränken. Deswegen lohnt sich für viele Aktionen ein Check. Der geht nach folgendem Schema:
$fql_query = array( 'method' => 'fql.query', 'query' => 'SELECT publish_stream FROM permissions WHERE uid = '.$facebook->getUser() ); $fql_info = $facebook->api($fql_query); print_r($fql_info); /* Array ( [0] => Array ( [publish_stream] => 1 ) )
Bedeutet: Wir dürfen (immernoch) die Pinnwand des Benutzers vollkritzeln. Wie das geht? Siehe direkt untendrunter.
7) Auf Pinnwand des Benutzers schreiben
Am besten – wie unter Punkt 8 oben erwähnt – vorher prüfen, ob die App überhaupt noch die Berechtigung dazu hat.
$facebook->api('/'.$facebook->getUser().'/feed', 'post', array( 'message' => 'Hey there! Message from the void.', 'name' => 'Appname', 'description' => 'Message description', 'caption' => 'Some Caption', 'picture' => 'http://img01.lachschon.de/images/78394_orly_owl.jpg', 'link' => 'https://d-mueller.de' ));
Sieht dann auf der Pinnwand so aus:
8) Öffentliche Informationen beliebiger User auslesen
Auch wenn ein Benutzer eure Applikation nicht erlaubt hat, ist ein kleines Subset an Infos trotz allem öffentlich auslesbar. Dabei zum Testen einfach schauen, welche ID euer Profil hat (Facebook Profilseite besuchen) – bei mir http://www.facebook.com/mueller.dav.
$public = $facebook->api('/mueller.dav'); print_r($public); /* Array ( [id] => 100000415342961 [name] => David Müller [first_name] => David [last_name] => Müller [link] => http://www.facebook.com/mueller.dav [gender] => male [locale] => de_DE ) */
9) Benutzerbild darstellen
<img src="https://graph.facebook.com/<?php echo $facebook->getUser(); ?>/picture">
getUser() liefert die Benutzer-ID des Users zurück (siehe letzter Schritt). Auch zum Laden des Benutzerbilds braucht man kein Einverständnis des Benutzers, ich könnte hier also beliebige Benutzer-IDs verwenden.
Clientseite
Prinzipiell geht alles, was auf der Serverseite ging ebenso mit Javascript. Auch der Zugriff auf die extrem mächtige Facebook Query Language. Es ist also immer abzuwägen, ob im jeweiligen Fall sinnvoller die serverseite oder die Clientseite zu verwenden ist.
1) Initialisierung
<div id="fb-root"></div> <script src="http://connect.facebook.net/de_DE/all.js"></script> <script> FB.init({ appId : 'your-appid', status : true, // check login status cookie : true, // enable cookies to allow the server to access the session xfbml : true // parse XFBML }); </script>
Danach kanns losgehen! Eigentlich sehr analog zur Initialisierung der PHP-Klasse, blos das kein secret-key angegeben wird. Wichtig: Unbedingt auf das fb-root-div vor Aufruf von FB.init achten. Sonst hagelts Fehlermeldungen.
2) Überprüfen, ob ein Benutzer eingeloggt ist
Der Code sollte selbstsprechend sein.
FB.getLoginStatus(function(response) //callback { if (!response.session) { alert("user is not logged in"); console.log(response); /* Object perms: null session: null status: "unknown" */ } else { alert("user is logged in"); console.log(response); /* Object perms: "{"extended":["status_update","photo_upload","video_upload","email","create_note","share_item","publi…" session: Object access_token: "182175161797277|2.k9LeCVa1qBVELkQXMuILkg__.3600.1291136400-100000415342961|ZtQwAJOTbOJe5Nf6nTWkb6PzA…" expires: 1291136400 secret: "secretkey" session_key: "2.k9LeCVa1qBVELkQXMuILkg__.3600.1291136400-100000415342961" sig: "signature" uid: "100000415342961" status: "connected" */ } });
3) Benutzer einloggen
Was hier passiert, ist das das typische Facebook-Login-Popup hochkommt. Es gibt 3 verschiedene Möglichkeiten, was nun passiert.
- Der Benutzer hat der App noch keinen Zugriff gewährt: Der Benutuzer loggt sich ein und erlaubt dann der App den Zugriff – oder eben nicht.
- Der Benutzer hat der App bereits den Zugriff erteilt:Er muss sich nur noch einloggen.
- Der Benutzer hat der App den Zugriff erteilt und kommt mit einer gültigen Session: Das Fenster geht sofort wieder zu und der User gilt als eingeloggt
FB.login(function(response) //callback { if (response.session) { console.log(response); /* Object perms: "read_stream,publish_stream,offline_access", session: Object { session_key="b089d77c93b5e25689470537-100000415342961", uid="100000415342961", more...}, access_token: "182175161797277|b089d77...3qTMrJmGcQiXszuf2apUbOk", expires: 0, secret: "secretkey", session_key: "b089d77c93b5e25689470537-100000415342961", sig: "signature". uid: "100000415342961" status: "connected", */ if (response.perms) { // user is logged in and granted some permissions. } else { // user is logged in, but did not grant any permissions } } else { // user is not logged in } }, {perms:'read_stream,publish_stream,offline_access'});
Hier fordern wir vom Benutzer die unten aufgelisteten Rechte. Er hat natürlich die Wahl, dies zu gestatten oder zu verneinen. Wie es auch kommt – wir haben die Wahl, in der Callback-Funktion auf alles entsprechend zu reagieren. Schön ist, dass sich Facebook selbst drum kümmert, ob der Benutzer die App erst erlauben muss oder ob er sich nur einloggen muss. Hat er die App noch nicht erlaubt, kommt nach dem Login einfach folgendes zusätzliches Formular, in dem der User die Vernetzung vornimmt:
Probleme mit dieser Art des Logins:
- Da es ein Popup ist, kann es sein, dass der Popup-Blocker zuuschlägt
- Unter Webkit kämpft das Facebook-Team gerade mit einem weniger charmanten Fehler, der den Login per Javascript auf die oben beschriebene Art nicht gestattet. Bisher (Stand 30.11.2010) ist das Problem noch nicht gelöst. Folgendes wird als Fehler geschmissen:
Es ist also gut zu überlegen, ob man das wirklich so und nicht per Weiterleitung zu Facebook und dortigem Login (beschrieben unter Serverseitig -> Punkt 3) oder mit dem noch folgenden Login-Button machen will.
4) Benutzer ausloggen
FB.logout(function(response) { console.log(response); /* Object perms: null session: null status: "unknown" */ if (response.session) { alert("logout failed"); } else { alert("logout successfull"); } });
5) FQL
Geht eigentlich ganz genau analog zu PHP auch clientseitig.
FB.api({ method: 'fql.query', query: 'SELECT name, pic FROM profile WHERE id=' + FB.getSession().uid }, function(response) { console.log(response); /* Object name: "David Müller" pic: "http://profile.ak.fbcdn.net/hprofile-ak-snc4/hs169.ash2/41534_100000415342961_1227664_s.jpg" */ });
Ist der Benutzer bei euch eingeloggt, kann auch alles an Infos ausgelesen werden, was euch gestattet wurde:
FB.api('/me', function(response) { console.log(response); /* Object birthday: "03/13/1989" education: Array[1] email: "mueller.dav@gmail.com" first_name: "David" gender: "male" id: "100000415342961" last_name: "Müller" link: "http://www.facebook.com/mueller.dav" locale: "de_DE" name: "David Müller" timezone: 1 updated_time: "2010-11-23T07:01:59+0000" verified: true */ });
6) Event-Listener
Es ist auch möglich, im typischen Javascript-Style auf Events zu reagieren. Ist also ein Benutzer bei euch auf der Seite unterwegs, lässt sich so flexibel auf Events wie ein- und ausloggen reagieren.
FB.Event.subscribe('auth.login', function() { alert("user logged in"); }); FB.Event.subscribe('auth.logout', function() { alert("user logged out"); }); //everything that's changing, including login and logout FB.Event.subscribe('auth.sessionChange', function(response) { if (response.session) { alert("user logged in"); } else { alert("user logged out"); } });
7) Der Facebook-Login-Button
Neben der Weiterleitung zu Facebook sicherlich die beste Lösung zum User-Login: Der offizielle facebook-Login-Button. Garantiert auch gut unter Webkit. Durch die Angabe von xfbml: true in der init-Funktion (Schritt 1) wird folgender Code in den eleganten blauen Facebook-Login-Button verwandelt:
</script> function callback() { //check if user is really logged in / granted all permissions } </script> <fb:login-button perms="email,user_birthday" onlogin="callback()"></fb:login-button>
Die perms sind genau wie der callback optional. Übrigens wird der callback unabhängig vom Erfolg des Logins aufgerufen. Wenn der Benutzer eurer App keine Rechte einräumt oder entnervt auf „abbrechen“ klickt, ist es eure Aufgabe, das im Callback zu überprüfen.
Das wars!
Die Auflistung der Möglichkeiten ist natürlich ganz und garnicht vollständig, aber das wichtigste sollte erschlagen sein. Für alles weitere gehts dann auf der offiziellen facebook-developers-Seite weiter.
Vielen Dank für den Artikel!
Hi,
kann ich auch die Anzahl der Fans einer Seite auslesen?
Aus einem bestimmten grund kann ich die Email adresse nicht lesen.. Ich habe es versucht aber irgend wie kann ich trotz req_perms => email keinen eintrag mit email finden… Kann es sein das vom eigentümer der app keine email adresse eingesehen werden kann ?
wenn ja dann habe ich ein Problem…
Ich frage mich nun, ob der FB-Nutzer nun einen Account in der eigenen Datenbank bekommt, was ja erforderlich ist, damit das eigene System funktioniert oder müssen alle Systeme so umgebaut werden, dass sie auch mit Fremdlogins arbeiten?
Bin leider schon bei Punkt 1 gescheitert:
„Auf der Github Seite die facebook.php und das Zertifikat herunterladen. “
Der Link zu Github funktioniert nicht (mehr).Wenn ich über Facebook suche, gelange ich zu dieser Seite:
https://help.github.com/articles/set-up-git
Bei der dortigen Downloadseite muss man eine Software für Windows etc. runter laden und installieren. Dass kann doch nicht richtig sein, bei einem PHP-Skript…
Ist wohl umgezogen, danke für den Hinweis. Neue URL ist hier: https://github.com/facebook/facebook-php-sdk/tree/master/src
Hi David,
auf der Suche nach einem Facebook API Tutorial bin ich auf deinen Blog gestoßen.
Danke für diese ausführliche Anleitung. Man findet selten Blogs in dieser Qualität.
Vielen Dank dafür!
Also ich plane de Einbau des Facebook-Logins aber FB macht mir da ein paar Probleme. Da ich zuerst ein Werbekampagne laufen hatte, hab ich nun ständig diese Kampagnenseite. Selbst wenn ich, aus der Mail von FB auf die Developerseite gehen will, kommt diese Werbeseite. Ich habe also keine Möglichkeit, mir eine ID für die API zu holen. Nun brauch ich wohl einen 2. Account, was wohl gegen die Nutzungsbedingunen verstößt.
Hi, es gehts auch einfacher…mit ein paar get und post requests :) im mom 220 zeilen code :)
Hi, danke für den Artikel, sehr gut beschrieben und viele Beispiele … Hast du eine Idee wie man auf die Pinnwand einer anderen Seite schreiben kann.. Also ich meine auf einer anderen Wall die man selber verwaltet … Bei mir klapt es irgendwie nur bei meiner eignen Wall … lg Andreas
Hi ich wollte das ausprobieren und hab eine einfache php seite mit
“,
’secret‘ => “,
‚cookie‘ => true
));
$facebook->api(‚/‘.$facebook->getUser().’/feed‘, ‚post‘, array(
‚message‘ => ‚Hey there! Message from the void.‘,
’name‘ => ‚Appname‘,
‚description‘ => ‚Message description‘,
‚caption‘ => ‚Some Caption‘,
‚picture‘ => ‚http://img01.lachschon.de/images/78394_orly_owl.jpg‘,
‚link‘ => ‚https://d-mueller.de‘
));
?>
leider bekomme ich dann immer die Meldung couldn’t connect to host … woran liegt das?
Hi,
Gutes Tutorial, aber:
Ich mache alles wie beschrieben, doch bei $facebook->api() kommt immer ein Fehler wie dieser:
Fatal error: Uncaught OAuthException: An active access token must be used to query information about the current user. thrown in /XXXXXXXX/API/base_facebook.php on line 1199
Was mache ich falsch?
Die API-Beschreibung ist veraltet. Du musst es auf die neue Version anpassen.