Facebook – pobieranie ostatnich wpisów z fan page

Jednym z najmniej skomplikowanych przykładów, na podstawie których można zaprezentować ideę API Facebooka jest pobieranie danych z wybranego fan page’a do streamu aplikacji internetowej. W artykule chciałbym przedstawić, jak w prosty sposób podpiąć stronę internetową tak, aby mogła pobierać dane z konkretnego fan page’a wykorzystując API Facebooka i oczywiście Symfony 2.

API Facebooka jest realizowane w modelu CAS (Central Authorisation System). Każda aplikacja dzięki przyznanemu przez Facebooka ID oraz sekretnemu kluczowi będzie mogła się zautoryzować przez API oraz pobrać token umożliwiający odpytywanie API o dodatkowe dane. W tym wypadku będziemy korzystać z Facebook PHP SDK (https://developers.facebook.com/docs/reference/php/).

Jednak, aby nie implementować komunikacji między oryginalną biblioteką Facebook PHP SDK, a Symfony posłużymy się FOSFacebookBundle (https://github.com/FriendsOfSymfony/FOSFacebookBundle), którego instalację oraz konfigurację opiszę w kolejny punktach.

Tworzymy aplikację

Aby komunikować się z API Facebooka będziemy potrzebowali zarejestrowanej aplikacji w centrum developerskim. W tym celu klikamy w button “+utwórz aplikację” na stronie https://developers.facebook.com/apps i uzupełniamy dane. Nazwa aplikacji jest obowiązkowa w przeciwieństwie do kolejnych opcji. App Namespace może się przydać w momencie komunikacji z OpenGraphem wykorzystywanym do historyjek i reklam facebookowych, a także będzie naszym adresem po stronie Facebooka (w naszym przypadku http://apps.facebook.com/xlabtestarticle ).

Po utworzeniu nowej aplikacji zostaniemy przekierowani na stronę edycji jej ustawień. Uzupełniamy podstawowe dane i dodajemy możliwość logowania się ze strony statycznej oraz zakładki Facebooka. Widoczne na załączonym zrzucie dane będą potrzebne podczas konfiguracji aplikacji – App ID oraz App Secret.

Przygotowanie Symfony do komunikacji z API Facebooka

Jako ideę programowania zawsze przyjmuję “nie wymyślać koła na nowo”. Dlatego skorzystamy z gotowego bundla FOSFacebookBundle implementującego service w dependency injection do komunikacji z API Facebooka.

Jego pełną dokumentację można znaleźć na stronie githuba: https://github.com/FriendsOfSymfony/FOSFacebookBundle .

Instalacja FOSFacebookBundle

1. Do pliku composer.json doklejamy w sekcji require kod odpowiedzialny za ściągnięcie biblioteki:

1
2
<span style="color: #000000">
{<br />&nbsp;"require":&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"friendsofsymfony/facebook-bundle":&nbsp;"dev-master",<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"facebook/php-sdk":&nbsp;"dev-master",<br />&nbsp;}<br />}</span>

2. Uruchamiamy composera (gdyby composer.phar nie został zainstalowany, dodatek A opisuje jak to zrobić)

1
composer.phar update friendsofsymfony/facebook-bundle

3. Dodajemy bundle do pliku AppKernel.php

1
2
<span style="color: #000000">
//&nbsp;app/ApplicationKernel.php<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;registerBundles()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;array(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;...<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;FOSFacebookBundleFOSFacebookBundle(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;...<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br /></span>

4. Dodajemy nowe ścieżki routingu w routing.yml

1
2
<span style="color: #000000">
&nbsp;&nbsp;&nbsp;&nbsp;#application/config/routing.yml<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_security_check:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pattern:&nbsp;&nbsp;/login_check<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_security_logout:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pattern:&nbsp;&nbsp;/logout</span>

 

5. Definiujemy ustawienia bundla według danych z pierwszej części artykułu

1
2
<span style="color: #000000">
&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;application/config/config.yml<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fos_facebook:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file:&nbsp;&nbsp;&nbsp;%kernel.root_dir%/../vendor/facebook/php-sdk/src/base_facebook.php<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alias:&nbsp;&nbsp;xlabtestarticle<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;app_id:&nbsp;193001437511739<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;secret:&nbsp;30d57175929a938e2ac93d234535520d<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cookie:&nbsp;true<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;permissions:&nbsp;[email]</span>

Opcja permissions jest przydatna podczas pobierania danych na temat użytkownika. Można poprosić go o dostęp do podstawowych danych, adresu email, znajomych, tablicy lub nawet opublikować w jego imieniu post na jego lub tablicy przyjaciela. Więcej informacji na ten temat można znaleźć w dokumentacji pod adresem: https://developers.facebook.com/docs/reference/login/.

6. Pozostaje jeszcze tylko zdefiniować providera użytkownika oraz zabezpieczoną sekcję aplikacji

1
2
<span style="color: #000000">
security:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;firewalls:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;since&nbsp;anonymous&nbsp;is&nbsp;allowed&nbsp;users&nbsp;will&nbsp;not&nbsp;be&nbsp;forced&nbsp;to&nbsp;login<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pattern:&nbsp;&nbsp;&nbsp;^/.*<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fos_facebook:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;app_url:&nbsp;"http://apps.facebook.com/appName/"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;server_url:&nbsp;"http://localhost/facebookApp/"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anonymous:&nbsp;true<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;access_control:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;{&nbsp;path:&nbsp;^/secured/.*,&nbsp;role:&nbsp;[IS_AUTHENTICATED_FULLY]&nbsp;}&nbsp;#&nbsp;This&nbsp;is&nbsp;the&nbsp;route&nbsp;secured&nbsp;with&nbsp;fos_facebook<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;{&nbsp;path:&nbsp;^/.*,&nbsp;role:&nbsp;[IS_AUTHENTICATED_ANONYMOUSLY]&nbsp;}</span>

Taka definicja access_control pozwoli nam zabezpieczyć jedynie część aplikacji wymagając autoryzacji z Facebookiem jedynie w routingu /secured/.

Pobieranie danych

Część zasadnicza tego artykułu, czyli… po konfiguracji i przygotowaniu Symfony 2 i aplikacji w Facebooku przechodzimy do implementacji pobierania ostatnich postów z wybranego fan page’a.

Pierwszym krokiem będzie pobranie unikalnego tokena zwracanego przez Facebook API podczas autoryzacji użytkownika. Będzie on przydzielony do naszej aplikacji.

W tym celu musimy chwilowo utworzyć akcję, do której będziemy mogli dostać się przez przeglądarkę internetową. Tworzymy nową ścieżkę routingu zabezpieczoną przez autoryzację Facebooka:

1
2
<span style="color: #000000">
_secured:<br />&nbsp;&nbsp;&nbsp;&nbsp;pattern:&nbsp;&nbsp;/secured<br />&nbsp;&nbsp;&nbsp;&nbsp;defaults:&nbsp;{&nbsp;_controller:&nbsp;AcmeDemoBundle:Welcome:secured&nbsp;}</span>

oraz akcję w WelcomeControllerze o nazwie securedAction();

1
2
3
<span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">WelcomeController&nbsp;</span><span style="color: #007700">extends&nbsp;</span><span style="color: #0000BB">Controller<br /></span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: #0000BB">securedAction</span><span style="color: #007700">()<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">get</span><span style="color: #007700">(</span><span style="color: #DD0000">'fos_facebook.api'</span><span style="color: #007700">)-&gt;</span><span style="color: #0000BB">getAccessToken</span><span style="color: #007700">());<br />&nbsp;&nbsp;&nbsp;}<br />}</span>
</span>

Po wpisaniu w przeglądarce http://localhost/facebookApp/web/app_dev.php/secured powinniśmy zostać przekierowani do strony autoryzacji Facebooka.

Jeżeli wszystko poszło dobrze to użytkownik powinien zostać prawidłowo zautoryzowany, a następnie przekierowany z powrotem do sekcji secured. Aby potwierdzić pełną autoryzację możemy zbadać obiekt $this->get(‘security.context’)->getToken()->getUser() . Jako użytkownik powinien być zapisany nasz Facebook ID.

Pobieranie ostatnich wpisów z wybranego fan page’a

Aby otrzymać stały dostęp do API Facebooka bez potrzeby wielokrotnej autoryzacji należy zablokować opcję odświeżania klucza API w ustawienia aplikacji na stronie developers.facevook.com/apps . Ustawienia te znajdują się w opcjach zaawansowanych i oznaczone są jako Reset Client Token – powinno być ustawione na “no”.

Po autoryzacji użytkownika z poziomu aplikacji przechodzimy do pobrania jego tokena, czyli unikalnego klucza sesji. Robimy to badając obiekt $this->get(‘fos_facebook.api’)->getAccessToken()

1
Przykład: string(112) "AAACviKYfwDsBAPAaNLhpJiLW8CZAfTPzfIG8XsDfFzFRZBSzuBVlwrTVZCm34NSMACzmuR27AE8iwZBgXQLXsPdGmJLXqs193UkrKy59XXXXX"

Tak pobrany string kopiujemy do konfiguracji aplikacji razem z fan page id dla którego chcemy pobrać dane, najlepiej do pliku parameters.ini jako:

1
2
3
fb.token = AAACviKYfwDsBAPAaNLhpJiLW8CZAfTPzfIG8XsDfFzFRZBSzuBVlwrTVZCm34NSMACzmuR27AE8iwZBgXQLXsPdGmJLXqs193UkrKy59XXXXX

fb.fanpageid = 60274674461

W końcu tworzymy akcję consoli, którą będziemy mogli wykorzystać do pobierania i zapisywania cyklicznie danych.

1
2
3
<span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">namespace&nbsp;</span><span style="color: #0000BB">Acme</span><span style="color: #007700"></span><span style="color: #0000BB">DemoBundle</span><span style="color: #007700"></span><span style="color: #0000BB">Command</span><span style="color: #007700">;<br /><br />use&nbsp;</span><span style="color: #0000BB">Symfony</span><span style="color: #007700"></span><span style="color: #0000BB">Bundle</span><span style="color: #007700"></span><span style="color: #0000BB">FrameworkBundle</span><span style="color: #007700"></span><span style="color: #0000BB">Command</span><span style="color: #007700"></span><span style="color: #0000BB">ContainerAwareCommand</span><span style="color: #007700">;<br />use&nbsp;</span><span style="color: #0000BB">Symfony</span><span style="color: #007700"></span><span style="color: #0000BB">Component</span><span style="color: #007700"></span><span style="color: #0000BB">Console</span><span style="color: #007700"></span><span style="color: #0000BB">Input</span><span style="color: #007700"></span><span style="color: #0000BB">InputArgument</span><span style="color: #007700">;<br />use&nbsp;</span><span style="color: #0000BB">Symfony</span><span style="color: #007700"></span><span style="color: #0000BB">Component</span><span style="color: #007700"></span><span style="color: #0000BB">Console</span><span style="color: #007700"></span><span style="color: #0000BB">Input</span><span style="color: #007700"></span><span style="color: #0000BB">InputInterface</span><span style="color: #007700">;<br />use&nbsp;</span><span style="color: #0000BB">Symfony</span><span style="color: #007700"></span><span style="color: #0000BB">Component</span><span style="color: #007700"></span><span style="color: #0000BB">Console</span><span style="color: #007700"></span><span style="color: #0000BB">Input</span><span style="color: #007700"></span><span style="color: #0000BB">InputOption</span><span style="color: #007700">;<br />use&nbsp;</span><span style="color: #0000BB">Symfony</span><span style="color: #007700"></span><span style="color: #0000BB">Component</span><span style="color: #007700"></span><span style="color: #0000BB">Console</span><span style="color: #007700"></span><span style="color: #0000BB">Output</span><span style="color: #007700"></span><span style="color: #0000BB">OutputInterface</span><span style="color: #007700">;<br /><br />class&nbsp;</span><span style="color: #0000BB">FbCommand&nbsp;</span><span style="color: #007700">extends&nbsp;</span><span style="color: #0000BB">ContainerAwareCommand<br /></span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;protected&nbsp;function&nbsp;</span><span style="color: #0000BB">configure</span><span style="color: #007700">()<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$this<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">setName</span><span style="color: #007700">(</span><span style="color: #DD0000">'demo:fb'</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&gt;</span><span style="color: #0000BB">setDescription</span><span style="color: #007700">(</span><span style="color: #DD0000">'XSolve&nbsp;facebook&nbsp;demo&nbsp;article'</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;<br />&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;protected&nbsp;function&nbsp;</span><span style="color: #0000BB">execute</span><span style="color: #007700">(</span><span style="color: #0000BB">InputInterface&nbsp;$input</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">OutputInterface&nbsp;$output</span><span style="color: #007700">)<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$fbToken&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getContainer</span><span style="color: #007700">()-&gt;</span><span style="color: #0000BB">getParameter</span><span style="color: #007700">(</span><span style="color: #DD0000">'fb.token'</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$fbSiteId&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getContainer</span><span style="color: #007700">()-&gt;</span><span style="color: #0000BB">getParameter</span><span style="color: #007700">(</span><span style="color: #DD0000">'fb.siteid'</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$content&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getContainer</span><span style="color: #007700">()-&gt;</span><span style="color: #0000BB">get</span><span style="color: #007700">(</span><span style="color: #DD0000">'fos_facebook.api'</span><span style="color: #007700">)-&gt;</span><span style="color: #0000BB">api</span><span style="color: #007700">(</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$fbSiteId</span><span style="color: #DD0000">/feed"</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(...)<br />&nbsp;&nbsp;&nbsp;}<br />}&nbsp;</span>
</span>

Do zmiennej $content ładowanych jest ostatnich 25 aktywności na wybranych fan page’u. Każdy rekord zwrócony z API Facebooka przez tą metodę posiada własny typ np. status, photo lub link, dodatkowo posiada informacje na temat daty publikacji, pełnego zestawienia zawartości, komentarzy oraz polubień.

Dodatkowe informacje na temat możliwości pobierania danych z fan page’ów można znaleźć w dokumentacji: https://developers.facebook.com/docs/reference/api/page/ .

Have fun!

Dodatek A

Szybka instalacja composera:
$ curl -s http://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer.phar

Dla leniwych:
$ alias composer=’/usr/local/bin/composer.phar’

[FM_form id="1"]