background image

Facebookowe 

Graph API

 udostępnia ciekawą funkcjonalność, dzięki której nasza aplikacja może 

być automatycznie powiadamiana o zmianie danych użytkownika lub strony, a także o odwołaniu 
któregoś z udzielonych wcześniej zezwoleń. Przyjrzyjmy się jak działają real-time updates i jak 
możemy z nich skorzystać.
Głównym celem udostępnienia tej funkcjonalności przez 

Facebooka

 było umożliwienie poprawy 

wydajności i czasu ładowania aplikacji poprzez trzymanie danych po stronie aplikacji i 
aktualizowanie ich tylko w momencie gdy się zmieniają, co owocuje mniejszą ilością odwołań do 

Graph API

. Można oczywiście wykorzystać real-time updates do innych celów, na przykład do 

wykonywania jakiejś akcji w momencie gdy interesujące nas dane ulegną zmianie.
Aby Facebook wysyłał naszej aplikacji powiadomienia o zmianach danych musimy zgłosić chęć ich
otrzymywania. Na chwilę obecną subskrybować można zmiany w obiektach user, 
permissions i page (tylko dane dostępne publicznie). Niestety, w przypadku obiektu user 
(dane użytkownika) nie mamy dostępu do wszystkich informacji - na dzień dzisiejszy możemy 
zasubskrybować zmiany w połączeniach feed (tablica użytkownika), friends (lista znajomych),
activities (aktywność), interests (zainteresowania), music (muzyka), books (książki), 
movies (filmy), television (telewizja), likes (lubiane strony) i checkins (aktualnie 
niedostępne w Polsce). Ekipa Facebook obiecuje jednak, że lista dostępnych powiadomień będzie 
się powiększać, tak więc warto raz na jakiś czas zerknąć do 

dokumentacji

.

Zacznijmy od zasubskrybowania powiadomień o zmianach danych użytkownika. Aby to zrobić 
musimy pobrać token OAuth dla naszej aplikacji, a następnie posługując się nim wysłać 
odpowiednie żądanie do 

Graph API

. Może to wyglądać na przykład tak:

Kod: 

Zaznacz cały

require('fb/facebook.php');

$facebook = new Facebook(array(
  'appId'  => '_id_naszej_aplikacji_',

  'secret' => '_sekretny_kod_naszej_aplikacji_',
  'cookie' => true,

));

// pobieramy token OAuth dla naszej aplikacji
$params = array('grant_type'    => 'client_credentials',

                'client_id'     => $facebook->getAppId(),
                'client_secret' => $facebook->getAppSecret());

$ch = curl_init();
$url = 'https://graph.facebook.com/oauth/access_token';

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);        
curl_setopt($ch, CURLOPT_POST, true);

curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$return = curl_exec($ch);

curl_close($ch);
$return_array = explode('=', $return);

$app_token = $return_array[1];

// dodajemy nową subskrypcję
$params = array('access_token'  => $app_token,

                'object' => 'user',
                'fields' => 'television,books,music,movies',

                'verify_token' => 'aaabbbccc',
                'callback_url' => 'http://nasz-

serwer.pl/katalog/rt_receive.php');
$ch = curl_init();

$url = 'https://graph.facebook.com/'.$facebook-

background image

>getAppId().'/subscriptions';

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);        
curl_setopt($ch, CURLOPT_POST, true);

curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$return = curl_exec($ch);

curl_close($ch);

Fragment kodu odpowiedzialny za dodawanie nowej subskrypcji wymaga kilku słów wyjaśnienia - 
w tablicy $params mamy bowiem dwa parametry, o których wcześniej nie wspomniałem. 
Parametr verify_token to dowolny ciąg znaków, służący do weryfikacji żądania przez skrypt 
odbierający powiadomienia. Adres tego skryptu należy podać w parametrze callback_url - 
musi być on dostępny w momencie dodawania subskrypcji i musi zwrócić poprawną odpowiedź. 
Przykładowy, prosty skrypt odbierający (nazwijmy go rt_receive.php) może wyglądać tak:
Kod: 

Zaznacz cały

// ten sam token co w skrypcie dodającym subskrypcję

define('VERIFY_TOKEN', 'aaabbbccc');
$method = $_SERVER['REQUEST_METHOD'];

   
if($method == 'GET' && $_GET['hub_mode'] == 'subscribe' && 

$_GET['hub_verify_token'] == VERIFY_TOKEN)
{

    echo($_GET['hub_challenge']);
}

elseif($method == 'POST')
{

    // obsługa powiadomienia
    $updates = json_decode(file_get_contents("php://input"), true);

    file_put_contents('updates_log.txt', 'updates = ' . print_r($updates, 
true));

}

Skrypt ten pełni dwie funkcje: odpowiada na żądanie dodania subskrypcji (dane przysłane metodą 
GET) i odbiera powiadomienia o zmianie danych (dane przysyłane metodą POST). Odbieraniem 
danych zajmiemy się później.
Jeśli wszystko poszło zgodnie z planem, to nasza aplikacja ma w tym momencie aktywną 
subskrypcję zmian danych w polach television, books, music i movies w obiekcie 
użytkownika. Od tej pory jeśli któryś z użytkowników naszej aplikacji zmieni dane w tych polach 
(np. polubi stronę jakiegoś serialu czy filmu albo usunie tego typu stronę ze swojego profilu), nasz 
skrypt rt_receive.php otrzyma powiadomienie.
Aby pobrać aktywne subskrypcje można użyć takiego skryptu:
Kod: 

Zaznacz cały

// pobieramy aktywne subskrypcje

$ch = curl_init();
$url = 'https://graph.facebook.com/'.$facebook->getAppId().'/subscriptions?

access_token='.$app_token;
curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);        

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$return = curl_exec($ch);

var_dump(json_decode($return, true));

background image

Warto dodać, że modyfikację aktywnych subskrypcji wykonuje się w taki sam sposób jak dodanie 
nowej. Przykładowo, jeśli mamy aktywną subskrypcję na pola television, music, books i 
movies, a następnie wyślemy zgłoszenie subskrypcji pól television i music, to nasza 
subskrypcja będzie obejmować tylko te dwa pola - pozostałe zostaną usunięte.
Jeśli zachodzi konieczność usunięcia wszystkich subskrypcji lub subskrypcji dla całego obiektu (np.
user), należy wywołać API metodą DELETE. Nie jest to typowe działanie, tak więc można 
posłużyć się poniższym przykładem:
Kod: 

Zaznacz cały

// usuwanie subskrypcji
$ch = curl_init();

$url = 'https://graph.facebook.com/'.$facebook->getAppId().'/subscriptions?
access_token='.$app_token.'&object=user';

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);        
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');

$return = curl_exec($ch);
curl_close($ch);

Wróćmy teraz do odbierania powiadomień przez nasz skrypt rt_receive.php. Powiadomienia 
otrzymujemy w formacie JSON, który transformujemy do tablicy (Array) funkcją 
json_decode(). Skrypt zapisał otrzymane dane do pliku updates_log.txt, tak więc możemy 
zobaczyć jak te dane wyglądają. Mogą mieć one na przykład taką formę:
Kod: 

Zaznacz cały

Array
(

    [object] => user
    [entry] => Array

        (
            [0] => Array

                (
                    [uid] => 990000505646950

                    [id] => 990000505646950
                    [time] => 1294519765

                    [changed_fields] => Array
                        (

                            [0] => television
                        )

                )
            [1] => Array

                (
                    [uid] => 990000505646952

                    [id] => 990000505646952
                    [time] => 1294519765

                    [changed_fields] => Array
                        (

                            [0] => music,
                            [1] => movies

                        )
                )

        )
)

Jak widać, powiadomienie zawiera tylko informacje o danych, które uległy zmianie (w tym 
przypadku u dwóch użytkowników) - nie zawiera dodanych lub usuniętych danych. Jeśli mamy 

background image

dostęp do danych użytkownika (zezwolenie offline_access), to możemy pobrać wartości 
zmodyfikowanych pól już na etapie odbierania powiadomienia o zmianach. Trzeba jednak 
pamiętać, że skrypt odbierający powiadomienia musi zakończyć działanie w czasie krótszym niż 15
sekund - jeśli tak się nie stanie, to Facebook potraktuje to jako timeout (przekroczenie 
maksymalnego czasu odpowiedzi) i wyśle powiadomienie ponownie.
Zakładając, że mamy zezwolenie offline_access, możemy zmodyfikowane dane pobrać w 
taki sposób:
Kod: 

Zaznacz cały

// zmienna $updates zawiera tablicę (Array) z informacjami o zmianach 
danych otrzymanymi od Facebooka

$params = array('access_token' => $app_token);
foreach($updates['entry'] as $entry)

{
    foreach($entry['changed_fields'] as $field)

    {
        // pobieranie zmodyfikowanych danych użytkownika

        $data = $facebook->api('/'.$entry['uid'].'/'.$field, 'get', 
$params);

        // zobaczmy co dostaliśmy
        var_dump($data);

    }
}

Oczywiście w prawdziwej aplikacji nie będziemy wyświetlać pobranych danych - możemy je 
zapisać do bazy lub wykorzystać je w inny sposób, na przykład umieszczając wpis na tablicy 
użytkownika, wysyłając mu e-mail czy wykonując jakąś akcję w naszej aplikacji. Jeśli 
zasubskrybujemy zmiany w liście znajomych (object: user, fields: friends), możemy na przykład 
stworzyć aplikację powiadamiającą użytkownika o tym, że ktoś usunął go ze znajomych.