Home  >  

Creating a Custom API for Flash using Facebook API and PHP

Author photo
AddThis Social Bookmark Button
In the previous article we discussed how to set up the framework for PHP, FB API and Flash. We did a lot of work to make this happen. We tested the framework only with very simple methods that made calls to the FB API and databases. In this article we are going to extend the sample to implement all necessary calls to the API. We will try to find the most important and needed fb API methods and teak them for usage in Flash. All the hard work will be accompanied by a sample that will make the whole article more interesting. We will create a small photo album viewer that will let you send notifications of type "I like this" for every photo to your friends. This sample will be more interesting.
series badge
Find the rest of this series on the series page.
At the end we should have a sample like this:
article4_img11_2.png
OK, we will simply go step by step to make this happen. We will take the application we previously created on Facebook and modify it. We do not need to create new Facebook application keys and secrets. We will also use the same main.fla we used before.
So, when we look on the whole project, there will be an main.swf that will live in the Facebook canvas, we will have a php services file that will act as a proxy between Facebook API and Flash. We will not need a database here, since we will not store any data about the users like scores or notes. Maybe this can be extended later on to make photo comments possible but this is not what we need for this application. We will also apply some fades and tweens at the end. Let's get started, this will be a lot of fun!

Step one: Prepare the Facebook API calls

There are nice tools out there that will help us in testing the calls we are going to use in an application. For developers its a great help since they can make sure that at least one module of the application is working fine. On face-boOK, you can find the Face-book API test tool located at (http://developers.facebook.com/tools.php). When you open the requested page in any of the browsers, you will have a screen like this:
article4_img1.png
As you can see there is complete overview of all possible Facebook API calls. If you want you can test them a bit to get a feeling of how the calls work and how the output looks like. You can select the output format to be either XML, PHP or JSON. In our case we need only PHP and the methods we will need in this case are:

friends.get()
photos.getAlbums()
photos.get()
notifications.send()
Notifications.send() is not listed in the list of calls but that is because Facebook doesnt want developers test notification messages by spamming users with test messages. Let’s examine all those calls one by one the make sure we know what we can expect later in our application.

friends.get()
When we click the button “Call Method" we get the following results:

Array
(
    [0] => 2022256
    [1] => 30811372
    [2] => 61802896
.
.
.
As we can see in this sample, as a result we receive a list of all friends, sorted in a nice array. It’s a standard index based array, not an associative array. It’s important that we see what kind of data structure the Facebook API calls send to the application. This tool is a nice way to visually represent that.

photos.getAlbums()
Select this method, in the empty “uids” field paste your own id from the upper “User ID” field. Hit the “Call Method” and you get a fancy multidimensional array:

Array
(
    [0] => Array
        (
            [aid] => 4769631031261152717
            [cover_pid] => 4769631031261460639
            [owner] => 1110516263
            [name] => blentave slike
            [created] => 1236249692
            [modified] => 1236249882
            [description] => 
            [location] => 
            [link] => http://www.facebook.com/album.php?aid=17869&id=1110516263
            [size] => 1
            [visible] => everyone
        )
Depending on how many albums you have, you get that many array elements. In my case, I have one album and its located at the 0 index in the array, and the element of this array is again an associative array. In this associative array you have everything you need to work with albums. First you have the album id, then you have the photo id of the cover photo of the album, the uid of the album owner, in case it's my id, the name of the album, time when created, time when modified, description, location, link to the album, size (number of photos inside and visibility. So in order to access all the stuff we have to code like this:

//access the name of first album
$myAlbums[0]["name"]

//access the name of second album
$myAlbums[1]["name"]

photos.get()
This is another very important method that will be used in this app. As you can see it gives you the photos of a specific album. OK, let's check what this method gives us. First of all, we need to pass the id of an album in this case its 4769631031261152717 from the previous example. So, when we click the "Call Method" then we see the following output:

Array
(
    [0] => Array
        (
            [pid] => 4769631031261460639
            [aid] => 4769631031261152717
            [owner] => 1110516263
            [src] => http://photos-h.ak.fbcd...
            [src_big] => http://photos-h.ak.fbcdn.net/...
            [src_small] => http://photos-h.ak.fbc...
            [link] => http://www.facebook.com/photo.php?p...
            [caption] => 
            [created] => 1236249793
            [modified] => 1236249882
        )

)
This result is similar to the previous one. Let's go through the properties. First we see pid, it's the actual id of the photo, then we see the aid, the owner id. Those parameters are known to us from the last sample. There is the src property that is the actual path to the image from the album on the Facebook server (no need for own image hosting, yippee). There is the src_big and the src_small property that references the big and the small version of the image, respectively. The link to the image, the caption and the time of creation and modification. So, we need to remember that this array is one element, so when an album has, for example, 10 images, we access the images this way.

$pics[0]["src"]

$pics[1]["src"]

$pics[2]["src"]
Just like in the previous sample the output is an index based array. The elements are associative arrays with properties described above. The other thing you have to note for this method is that you need pass the id of the album, this is done with the getAlbums() method.

notifications.send()
This is another method necessary for implementing the application. The original signature is notifications_send(uid, 'Your message here', 'app_to_user'). We can't test the method directly here in the test console. The method sends notifications to the Facebook notifications tray in the lower right corner.
article4_img2.png
This is a great way to quickly notify the users of some event in your application. In my opinion, it's every better then emailing the user. Email can get spammy and messy and users will not pay much attention to that. The notifications tray is the element for us and we have the tools to make it work for us.

Step two: Create the proxy AMFPHP class file

All we need to do now is to implement those methods in PHP to work for Flash. We will implement those functions:

getAlbums()
getAlbum()
getAlbumCovers()
getPhoto()
sendNotification()
So, the first functions will look like this:

function getAlbums($uid, $sessID){
 	$this -> init();
 	$facebook = new Facebook(API_KEY, SECRET);
 	$facebook->set_user($uid, $sessID);
 	$albums = $facebook->api_client->photos_getAlbums($uid, null);
 	return $albums;
}

function getAlbum($uid, $aid, $sessID){
 	$this->init();
 	$facebook = new Facebook(API_KEY, SECRET);
 	$facebook->set_user($uid, $sessID);
 	$fql = "SELECT pid, aid, owner, src, src_big, src_small, link, caption, created FROM photo WHERE aid=".$aid;
 	$photos = $facebook->api_client->fql_query($fql);
 	return $photos;
}

function getAlbumCovers($uid, $sessID){
 
 	$albums = $this -> getAlbums($uid, $sessID);
 	$covers = array();
 
 	$facebook = new Facebook(API_KEY, SECRET);
 	$facebook->set_user($uid, $sessID);
 
 	if(!$albums){
  		return $covers;
  	}
 		
 	while(list($key, $val) = each($albums)){
  		$cover_pid = $albums[$key]["cover_pid"];
  		$aid = $albums[$key]["aid"];
  		$name = $albums[$key]["name"];
  		$fql = "SELECT src, src_big, src_small, link, caption FROM photo WHERE pid = ".$cover_pid;
  		$photos = $facebook->api_client->fql_query($fql);
  		if(is_array($photos)){
   			$photo = array("src" => $photos[0]["src"], "src_big" => $photos[0]["src_big"], "src_small" => $photos[0]["src_small"], "link" => $photos[0]["link"], "caption" => $photos[0]["caption"], "aid" => $aid, "name" => $name);
   		} else {
   			$photo = array();
   		}
  		array_push($covers, $photo);
  	}
 
 	return $covers;
 
}

function getPhoto($uid, $pid, $sessID){
 
 	$facebook = new Facebook(API_KEY, SECRET);
 	$facebook->set_user($uid, $sessID);
 		
 	$fql = "SELECT src, src_big, src_small, link, caption, owner FROM photo WHERE pid = ".$pid;
 	$photos = $facebook->api_client->fql_query($fql);
 			
 	return $photos[0];
 
}

function sendNotification($toUids, $uid, $msg, $sessID){
 	$this -> init();
 	//send notification
 	$facebook = new Facebook(API_KEY, SECRET);
 	$facebook->set_user($uid, $sessID);
 	$sent = $facebook->api_client->notifications_send($toUids, $msg, 'app_to_user');
 	return $sent;
}
We don’t need to go closer into any detail we just need to know that the getAlbumCovers() function returns the covers of the albums so we can display a nice gallery of album covers before the user decides what album he wants to see. The whole TestServices.php can be seen here, I won't waste space here for the complete script. All the functions act the same way as it is described in the previous sample. When, for example, getAlbums() is called, the method includes all the files we need to Facebook, creates a new Facebook API instance, sets the current user with the proper session id and makes the call. You can see in all the methods, all functions are structured as the same. Check the PHP file and place it in the services folder of your AMFPHP installation folder on the server. we can now safely move on to Flash as the PHP part is prepared.

Step three: Create the Flash frontend

Finally we are off to the final stage of the development, the Flash part. So, for now simply open the main.fla you created from previous articles. The document should be resized to 700 x 500 pixels.
article4_img3.png
Next, we need to create a movieclip that will act as a display container for images. So for that, go to Insert -> New Symbol and create an empty MovieClip called "ImageViewer".
article4_img4.png
You don’t need to export that for ActionScript. After you create that, you will be directed to the screen where you can work on the movie clip.
article4_img5.png
OK, the next thing you do here is to place two buttons (you can create them or you can use the common library) and to place the right and left in the movie clip, like on the image below:
article4_img6.png
Name the right nextImg_btn the left prevImg_btn. Place a UILoader on the stage between both buttons:
article4_img7.png
Name it img_mc in the property inspector. We can now go back to the main timeline to add some code. On the main timeline we need to have two layers, the lower one for all clips and components we place on it, the upper one for AS.
article4_img8.png
Publish the movie and upload it to your server, we need to make sure that there are no errors until now. We will not add any code, and will not clips to the main timeline. Just publish, upload to server and check the app in the Facebook canvas, I hope you have a screen like below and no errors:
article4_img9.png If this works, we are half way there! This step is important to make sure we uploaded the swf to the correct folder, etc. Those small errors can cost us a lot of time and headache if we don’t take care about the small things. Open the fla again and paste the following code into the first frame of the upper layer:

//get the Facebook parameters
var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;
var uid:String = String(paramObj["fb_sig_user"]);
var sessID:String = String(paramObj["fb_sig_session_key"]);

//get the base url of the swf, to improve portability of code
var baseURL:String = Tools.getBaseURL(LoaderInfo(this.root.loaderInfo).loaderURL);

//concat the connection string
var gatewayUrl:String = baseURL + "amfphp/gateway.php";

//create a new net connection
var gateway:NetConnection = new NetConnection();
//connect to gateway
gateway.connect(gatewayUrl);

//create responders for the calls
var responder:Responder = new Responder(onResult, onFault);

//call the method
gateway.call("TestServices.sayHi", responder);

//this callback will receive the results
function onResult(result):void{
 	
 	trace(result);
}

//catch the fault
function onFault(fault):void{
 	trace('onFault invoked');
 	trace(fault.description);
}
In FlashTracer you should see a “hi” message, this is a sign that Flash has connected to AMFPHP and we can call other methods without problems. article4_img10.png Now place the "ImageViewer” on the stage, on the lower layer of the main timeline. Name it imgViewer_mc in the property inspector. Now, we need to load the images. We will call getAlbumCovers, so we will modify the code like this:

//create responders for the calls
var albumResponder:Responder = new Responder(albumsLoaded, onFault);

//call the method
gateway.call("TestServices.getAlbumCovers", albumResponder, uid, sessID);

//this callback will receive the results
function albumsLoaded(result):void{
 	
 	trace("Albums are loaded: " + result);
 	
}

//catch the fault
function onFault(fault):void{
 	trace('onFault invoked');
 	trace(fault.description);
}
And the result we receive is:

Albums are loaded: [object Object],[object Object],[object Object],[object Object]
This means I have four albums and of course it depends from account to account on facebook. Now we need to modify the code inside ImageViewer to receive the images and display all the stuff:

var albSrcImg:Array = new Array();
var aids:Array = new Array();
var currIndex:Number = 0;

var srcImg:Array = new Array();

var mode:String = "albums";

nextImg_btn.addEventListener(MouseEvent.CLICK, nextImage);
prevImg_btn.addEventListener(MouseEvent.CLICK, prevImage);

function setAlbums(albums:Object):void{
 	
 	mode = "albums";
 	
 	for(var prop in albums){
  		
  		var src:String = albums[prop]["src"];
  		var aid:String = albums[prop]["aid"];
  		
  		albSrcImg.push(src);
  		aids.push(aid);
  		
  	}
 	
 	img_mc.source = albSrcImg[0];
 	
}

function nextImage(e:MouseEvent):void{
 	if(mode == "albums"){
  		if(currIndex == albSrcImg.length - 1){
   			return;
   		}
  		currIndex++;
  		img_mc.source = albSrcImg[currIndex];
  	} else {
  		
  		trace("hej...");
  		
  		if(currIndex == srcImg.length - 1){
   			return;
   		}
  		currIndex++;
  		img_mc.source = srcImg[currIndex];
  	}
}

function prevImage(e:MouseEvent):void{
 	if(mode == "albums"){
  		if(currIndex == 0){
   			return;
   		}
  		currIndex--;
  		img_mc.source = albSrcImg[currIndex];
  	} else {
  		if(currIndex == 0){
   			return;
   		}
  		currIndex--;
  		img_mc.source = srcImg[currIndex];
  	}
}
When you add this code inside the ImageViewer clip and call the function setAlbums from the callback:

//this callback will receive the results
function albumsLoaded(result):void{
 	
 	imgViewer_mc.setAlbums(result);
 	
}
You should see the result showing albums covers in the swf:
article4_img11.png
Cool! The next thing we need to do it to display the actual images from the album when the album is clicked. We will do that this way.
We need to be able to click on the album cover, after that the images should be loaded from the album and displayed. So, let's add the click handler to the UILoader:

img_mc.addEventListener(MouseEvent.CLICK, albumClicked);

function albumClicked(e:MouseEvent):void{
 	var s = new SuperEvent();
 	s.add("aid", aids[currIndex]);
 	dispatchEvent(new SuperEvent("albumClicked"));
}
SuperEvent is a class I created that comes in handy when you want to dispatch an event with properties. You can download the class here and put it into your project folder. Back to the main timeline, we need to register the listener for this event like this:

imgViewer_mc.addEventListener("albumClicked", albumClicked);

function albumClicked(e:SuperEvent):void{
 
 	var aid = e.get("aid");
 	trace("Clicked on album id: " + aid);
 	
}
 
<div style="text-align: left;">When clicked, we need to load the photos of this album:</div>

function albumClicked(e:SuperEvent):void{
 
 	var aid = e.get("aid");
 	gateway.call("TestServices.getAlbum", photoResponder, uid, aid, sessID);
 	
}
Note that before we must create a responder for photos:

var photoResponder:Responder = new Responder(photosLoaded, onFault);
and the callback:

function photosLoaded(result):void{
 	
 	trace("photo loaded..." + result);
 	
}
We should get a result like this:

photo loaded...[object Object],[object Object]
OK, now we need to display the images, so we add add his to ImageViewer:

function setImages(images){
 	
 	mode = "images";
 	
 	currIndex = 0;
 	
 	for(var prop in images){
  		var src:String = images[prop]["src"];
  		srcImg.push(src);
  	}
 	
 	img_mc.source = srcImg[0];
 	
}
We finally have the code working!
I will not reveal everything because I want you to try it out. Try adding a button where the user can switch back to albums. Also, try to add a caption of each album above the album so the user can navigate more easily between them.
In case you have, trouble, download the FLA here:ria.fla


Continue to Part 5, Using the New Facebook ActionScript 3.0 Library

To view the entire series please visit http://www.insideria.com/series-facebook-dev.html

Read more from Mirza Hatipovic. Mirza Hatipovic's Atom feed mirzahat on Twitter

Comments

8 Comments

Dara said:

Hi Mirza,

I am enjoying the series very much. Thank you.

It is probably staring me in the face, but I can't find the SuperEvent.as

thanks again,

Dara.

respect ... this article help me to underspend some details

Phoxer said:

Hi, I can't find an example for Adobe ActionScript 3 Facebook Api
about SendNotification .. please can you send me and example?

Thanks..

kc said:

May I know where can I get the SuperEvent.as?

kc said:

Hi, where can I find the SuperEvent.as?

Manish said:

Hi Mirza,

Lots of thanks for nice series.
I can't find the SuperEvent.as i just created the CustumEvent but i did understand this part
var aid = e.get("aid");

so if you can send me your SuperEvent.as file then it will help full to understand

thanks again,

Manish

Very interesting post, thanks for sharing :)

paul said:

can you post the SuperEvent class? It's not linked in the tutorial.

Leave a comment


Tag Cloud

Question of the Week: Dream App

If you had an unlimited budget and unlimited resources what application would you build and why would you build it?

Answer

Latest Features

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.