Building a Facebook Application, Start to Finish Understand the deepest things !

Building a Facebook Application, Start to Finish Understand the deepest things


Building a Facebook Application

By now you should have a good understanding of how Facebook allows you to implement your own code to extend its platform. I’ve covered how the different parts work, and I hope you’ve been able to take portions of the platform for a test-drive. However, I haven’t talked about how all these pieces fit together. To that end, this chapter focuses on developing a Facebook application from start to finish. For this example, I’ll show how to develop a game review application. The application will allow users to rate games, write reviews, and interact with one another. Now, I’ll preface this chapter with a notice that the driving force behind this application’s design decisions is to show different aspects of the Facebook platform and may, at times, diverge from how you might ordinarily design and implement your own applications. Please keep in mind that there are multiple (and at times, better) ways to accomplish the same result, so if you see a better way to implement a specific element in the code examples, please, by all means, hack away. You probably also have a favorite integrated development environment (IDE) that you use when developing your applications. I’ll be using Eclipse as the IDE for this chapter because it provides a really great set of tools for developing in almost every language. Since Facebook Markup Language (FBML) is a superset of Hypertext Markup Language (HTML), the PHP Development Tools (PDT) plug-in will have most of the tags you will use (it just doesn’t know about the Facebook-specific tags). I’ll also show how to use some of the other Eclipse plug-ins to help you develop the database back end, as well as manage and test your code. Setting Up Eclipse IBM developed Eclipse as a Java IDE but soon open sourced the project and established the Eclipse Foundation, which hosts a growing number of extensible frameworks, tools, and runtimes in many different languages. And, with its multilanguage support, Eclipse provides a convenient platform when you’re developing in multiple languages for a given project. 72 Building a Facebook Application, Start to Finish You can download the Eclipse IDE from http://www.eclipse.org/downloads/. The only other requirement to run this software is that you have a Java runtime installed on your system (JRE 5 is recommended, and JRE 1.4.2 is the minimum). If you need the latest Java Runtime Environment (JRE), you can download it from Sun at http://java.sun.com. If you’re not sure which version of Java you have installed, you can open a command prompt or terminal window and type the following: java -version You should see something along the lines of the following stating what JRE you have installed: Java version "1.6.0_04" Java(TM) SE Runtime Environment (build 1.6.0_04-b12) Java HotSpot(TM) Client VM (build 1.6.0_04-b12, mixed mode, sharing) If your JRE version is less than 1.4.2, you’ll need a new version. The download page for Eclipse displays several options for the different packages available. For the purposes of this book, you just want the latest Eclipse Classic package for your operating system. Once you’ve downloaded the software, simply unzip/untar the file to a convenient location (such as C:\eclipse or /opt/eclipse). To start the Eclipse IDE, launch the eclipse executable in the eclipse folder. Note ➡ At the time of this writing, the most recent version of Eclipse is Europa (3.3). You may be running Eclipse 3.4 (Ganymede) or some other future version of Eclipse. Just replace mentions of Europa with whatever the name of the instance of Eclipse is that you’re running. When you launch the IDE, you will be prompted for the location where you want to set up your workspace. You can accept the default, or you can change this to a more convenient location. Now out of the box, the IDE isn’t that useful because, as mentioned, IBM originally developed this as a Java IDE. You’ll need to add a couple of extensions before you can start developing. The first plug-in to add is the Remote System Explorer End-User Runtime extension from Eclipse. This plug-in will allow you to connect to your remote system to make edits (it supports SSH/SFTP, FTP, Local, Telnet, and Unix and Windows shares). I’ll explain how to install it in the following sections. Building a Facebook Application, Start to Finish 73 Using Plug-Ins One of the most powerful aspects of Eclipse is its extensibility through plug-ins. You’ll use several of the official plug-in projects supported by the Eclipse Foundation to add the ability to connect to your remote site, have PHP syntax highlighting, and connect to your database instance. I’m sticking to the plug-ins developed as part of the Eclipse project, but there are a lot of other plug-ins that may fit your development cycle better. A good place to look for these plug-ins is the Eclipse Plugin Central web site at http://www.eclipseplugincentral.com/. Remote Project Support (FTP/SFTP) Eclipse recently repackaged its set of plug-ins to allow remote access to different file systems in one Remote System Explorer End-User Runtime plug-in. To install this plug-in, use the Europa Discovery Site (a project software repository for Eclipse) by clicking Help > Software Updates > Find and Install, as shown in Figure 4-1. Select the Search for New Features to Install in the Feature Updates Wizard, and click Next. Click the Europa Discovery Site check box to search, and click the Finish button. If you haven’t selected the option to automatically select a mirror, you will be prompted to manually select a mirror (make sure you pick one that’s close to you). 74 Building a Facebook Application, Start to Finish Figure 4-1. Eclipse updates Once the mirror has been scanned for the software, expand the Europa Discovery Site, scroll down and expand the Remote Access and Device Development option, and select Remote System Explorer End-User Runtime. Then click Next. On the Feature License screen, select the option to accept the license, and click Next. You should have only one feature to install, on the next screen, and now click Finish to begin the installation (Figure 4-2). Building a Facebook Application, Start to Finish 75 Figure 4-2. Installing the Remote System Explorer End-User Runtime plug-in Once the plug-in has been downloaded, Eclipse will prompt you to restart the IDE. Go ahead and restart because it takes only a moment. PHP Development Tools The next plug-in you’ll install is the PDT plug-in from Eclipse. However, Eclipse doesn’t include this tool in its default listing, so you have to add it to the list of repositories. To 76 Building a Facebook Application, Start to Finish start, you again select Help > Software Updates > Find and Install, making sure the Search for New Features to Install option is selected. Then click Next. Click the New Remote Site button, name the update site PDT, enter the URL of http://download.eclipse.org/tools/pdt/updates/, and click OK (Figure 4-3). Figure 4-3. Eclipse PDT update Make sure the update site PDT and the Europa Discovery Site are selected, and click Finish. After you select the mirror, expand the tree PDT > PDT Features, and select PDT Features (see Figure 4-4). You’ll notice that there’s an error message at the top of the page letting you know that there are required features that you need to install. Expand the Europa Discovery Site > Web and JEE Development branch, and select the Web Standard Tools (WST) Project option. There are still unsatisfied dependencies, so now click the Select Required button, which will then select any additional packages that need to be downloaded. Building a Facebook Application, Start to Finish 77 Figure 4-4. Eclipse feature installation Click Next to view the individual licenses for each of the packages you need to download. After you’ve read them (you did read them, right?), accept the license agreement, and click Next. Then click Finish. After the software is finished installing, restart Eclipse. 78 Building a Facebook Application, Start to Finish Note ➡ PHPEclipse (http://www.phpeclipse.de) is another popular extension. It allows you to control Apache and MySQL from within Eclipse, which can save you some time. Joomlatwork (http://www.joomlatwork.com) has also developed an Eclipse package (to save you all the installation headaches) that you can download called PHP Development Studio. There’s a free version as well as a paid version that includes some optimizations. You can edit the setting for PDT by selecting Window > Preferences and expanding the PHP branch. It’s worth looking at all the settings you can set to be familiar with them should you want to change anything in the future. Data Tools Platform SQL Development Tools Lastly, you’ll install a SQL editor, along with some tools to ease working with your database back end. These tools are packaged in the Database Development branch of the Europa Discovery Site. Although you may already have a favorite tool for interacting with your relational database management system, the fact that Eclipse has an integrated tool for working with your data can be a boon to development. As before, open the Europa Discovery Site in the updater. Then select the entire Database Development tree from the options, and click the Select Required button to satisfy the dependencies, as shown in Figure 4-5. Building a Facebook Application, Start to Finish 79 Figure 4-5. Data Tools Platform plug-in installation After you’ve installed the plug-in and restarted Eclipse, the last thing to do is get the JDBC driver for your particular database back end. The examples in this book are using MySQL, so you can head over to the MySQL Connector/J web site (http://www.mysql.com/products/connector/j/) to download the latest driver. After saving the tarball to your hard drive, extract it to a convenient location: tar zxvf mysql-connector-java-5.1.X.tar.gz 80 Building a Facebook Application, Start to Finish tar zxvf mysql-connector-java-5.1.X.tar.gz mv mysql-connector-java-5.1.X/mysql-connector-java-5.1.X-bin.jar ~/java/jdbc/mysql The previous example places the JDBC driver for MySQL in the current user’s java/jdbc/mysql directory. If you’re a Windows user, this is equivalent to C:\Documents and Settings\\java\jdbc\mysql or C:\Users\\java\jdbc\mysql. Wherever you decide to put these files, remember where they are! The only remaining task is to tell Eclipse where the driver is. Open Eclipse’s preferences (in the Window option of the taskbar), expand the Connectivity branch, and click Driver Definitions. From there, scroll down to the MySQL Section, click 5.1, and click Add (see Figure 4-6). Figure 4-6. Adding the JDBC driver Building a Facebook Application, Start to Finish 81 Expand the Driver Template tree until you get the MySQL JDBC Driver template (Figure 4-7), and click OK. Figure 4-7. New driver definition You will notice that Eclipse knows to look for the mysql-connector-java-5.1.X-bin.jar file you extracted earlier but doesn’t have the path to the actual file. You correct this by clicking the driver file and clicking the Edit Jar/Zip option on the right. Just navigate to where you extracted your MySQL JDBC driver to, and click Open. This will clear the error for connecting to MySQL 5.1 database servers, so you can finish up by clicking OK until the dialog boxes are all closed. To test your connection, change to the Database Development Perspective (Window > Open Perspective > Other). In the dialog box, select Database Development, and click OK. From the wizard in the left toolbar (Figure 4-8), click the New Connection Profile icon, select Generic JDBC Connection, and click Next. Give a name and description for your connection, and select whether to establish the connection when Eclipse starts. This will cause Eclipse to take slightly longer to start up, or you can just establish the connection when you need it. 82 Building a Facebook Application, Start to Finish Figure 4-8. Adding a new database connection In the New JDBC Connection Profile Wizard, select MySQL JDBC Driver from the drop-down list. This autopopulates most of the fields; all you need to do is edit them to match your environment (see Figure 4-9). Figure 4-9. New JDBC connection profile Building a Facebook Application, Start to Finish 83 Assuming everything went well and there weren’t any errors, you now have direct access to the data on the server. You can create a new SQL file for any defined projects in Eclipse by selecting File > New > SQL File (if you don’t see it, select File > New > Other, expand SQL Development, select SQL File, and then click Next). Note ➡ If you’re working with a hosted database, make sure that the database server will accept outside connections. If not, you may need to edit your configuration files to include the IP address of the location from which you are working. Another alternative is to set up a local database that you can work with and then dump your SQL to your production server. In the Create SQL File Wizard, give your file a name, select the database server type of MySQL_5.1, and select your newly created connection profile and database name. Once your connection is established, you can test your code by writing it, right-clicking the contents of the file, and selecting Execute All. You can also execute selected text by first selecting the portion of the SQL statement to execute, right-clicking, and selecting Execute Selected Text. Connecting to Your Web Server Now that the IDE is properly set up, let’s set up the connection to your remote site. To do this, you’ll change the perspective to the Remote System Explorer by selecting Window > Open Perspective > Other and selecting Remote System Explorer. As part of a hypothetical sever configuration, let’s say that your domain (www.foobar.com) is set up for FTP access. To set up access, click the Define a Connection to Remote System button at the top of the Remote Systems toolbar on the left (see Figure 4- 10). 84 Building a Facebook Application, Start to Finish Figure 4-10. Adding an FTP connection This will launch a wizard for you to add your site definition. Once you have completed the wizard, you can then connect to your web site by right-clicking the site definition and selecting Connect. This will give you live access to the files on your server to develop and edit your files as needed. Layout Out the Project For the purposes of this chapter, I’ll show how to lay out your files in a rather simple manner, with each page serving a single purpose. You’ll also create a layout to separate the files that you don’t write into a separate folder. Since you’re using the Remote System Explorer, you’ll use this plug-in to help you set up the project in Eclipse. You first need to set up an Eclipse project using the Remote System Explorer. This is a simple task, but it’s not immediately evident if you’ve never done it before. Essentially, once you’ve created a connection to a remote resource, find the root folder you want to use as your project by expanding the directory listing in the left toolbar (shown earlier in Figure 4-10). Right-click the folder, and click Create Remote Project (Figure 4-11). This will set up a new project that you’ll be able to see in the Package Explorer, and it will simplify a lot of tasks. Building a Facebook Application, Start to Finish 85 Figure 4-11. Creating a remote project Before you go any further, let’s change views to the PHP editor. Simply click the Open Perspective button (Figure 4-12) in the upper-right corner, select Other, and then choose PHP. 86 Building a Facebook Application, Start to Finish Figure 4-12. Changing the Eclipse perspective This will change the perspective to the PHP editor from the PDT project. There’s not much to look at right now, but I’ll go through some of the features after you get a bit further in your setup. The next step is to create some folder structure. You want to get the Facebook client library files in a lib folder under the root. First, you need to download the most recent version of the files. They’re available for download at http://developer.facebook.com/resources.php. And, if you have wget (for example, you’re not using Windows), you can download the client library with the following: wget http://developers.facebook.com/clientlibs/facebook-platform.tar.gz tar zxvf facebook-platform.tar.gz After you’ve extracted the files, you need to get them into the project. First, create a folder under the root by right-clicking the root folder in Eclipse and selecting New > Folder. Then just type lib, and click Finish. Now select the newly created folder, right-click, and select Import. Expand the General tree, select File System, and click Next (Figure 4- )

Now, navigate to where you extracted the client library, and click OK. Select the files
facebook_desktop.php, facebook.php, and facebookapi_php5_restlib.php, and click Finish
(see Figure 4-14).
88 Building a Facebook Application, Start to Finish
Figure 4-14. Importing Facebook client libraries
Next, for convenience, let’s set up a file that you can include on your pages with some
of the information you’ll be using throughout the application. You’ll create another folder
called config and create a new file named config.inc.php. So, create the folder as you did
before; then create a new file by right-clicking the config folder and selecting New PHP
Building a Facebook Application, Start to Finish 89
File. Name the file config.inc.php, and click Next. Choose New Simple PHP File as the
template, and click Finish.
Note ➡ If you don’t see the option to create a new PHP file when you right-click a folder, make sure you are
in the PHP perspective.
In your new file, let’s include some code. The two most important pieces of information
you’ll need on every page is the API key and secret for your application. In case you didn’t
write them down when you applied for your application key, you can get to them in the
Developer application by clicking My Applications in the top right.
So, let’s add some code to your page. Using the code Facebook provides developers as
a template, you’ll set up your main include configuration as follows:
<?php
/**
 *
* File: config.inc.php
* This is the configuration file for the application
 *
 */
/*********************** Facebook Configuration ***********************/
// define the debug level (true|false)
$facebook_config['debug'] = true;
// define your API Key and secret
$facebook_config['api_key'] = '<your_api_key>';
$facebook_config['secret'] = '<your_secret>';
// include the facebook client library
require_once = '<path_to_libraries>/facebook.php';
// create the facebook object
$facebook = new Facebook($facebook_config['api_key'], $facebook_config['secret']);
// require users to be logged in
$user = $facebook->require_login();
// define your callback URL
90 Building a Facebook Application, Start to Finish
$callback_url = '<your_callback_url>';
?>
Note ➡ So, what’s the deal with the .inc. in the file name? Something you don’t want to happen is for
some of this information to be available to the Internet. To make sure these files are secure, it’s a good idea
to block these with .htaccess with a snippet like this:
<Files *.inc.php>
Order deny,allow
Deny from all
Allow from localhost
</Files>
In this code, you’ll notice at the top of the file that you set the debug level to true. This
is helpful while you’re developing your application, but make sure you set this to false
once you get ready to deploy your application!
Next I’ll show how to set up a page with some visual aspects for your application. It
won’t be anything fancy, just a page that you can use to actually see something when you
go to Facebook. You’ll create a new index file in the root. However, before you do this, I’ll
take a second to show how to edit PHP templates to include some of your specific needs
when developing your applications.
To edit the templates, click Window > Preferences. Then expand the PHP tree, and
select Templates (see Figure 4-15).
Building a Facebook Application, Start to Finish 91
Figure 4-15. PDT PHP templates
To add a new template, click the New button in the upper-right corner. Name this new
template New Facebook PHP, and change Context to New PHP. A description isn’t
necessary, but add the following in the Pattern area (see Figure 4-16):
<?php
/**
* File:
* Description:
 */
require_once('config/config.inc.php');
?>
92 Building a Facebook Application, Start to Finish
Click OK and then OK again when done.
Figure 4-16. PHP template
Now when you create new pages for your application, this information will
automatically be added. With that small task out of the way, let’s make your first page.
Create a new PHP file by right-clicking the root folder and selecting New > PHP File.
Name the file index.php, and click Next (not Finish). On the next screen, select the newly
created new Facebook PHP file, and then click Finish. You now have a skeleton file for
your application.
Next, you just need to fill in something on the page to make it actually have a display.
For this, you’ll use some FBML to display a success message to yourself to make sure
everything is working. Add the following to the following to your page (below the PHP):
<fb:success
 message="Congratulations! Your first application is up and running..." />
If you take a look at your application now (you remembered to save it, right?) by
navigating to http://apps.facebook.com/<your_app_name>, you should first be prompted to
add the application, and then you will see the screen shown in Figure 4-17 in the main page
of your application.
Building a Facebook Application, Start to Finish 93
Figure 4-17. FBML success
Before you get too far into the UI design, let’s take a step back and do a little planning
for your database back end.
Creating the Database
When developing a web application, one of the more complex tasks is developing a
database back end. For the purposes of this example, I’ll be using MySQL since it’s quite
typical for developers to have this as their back end. If you’re using another RDBMS such
as PostgreSQL, Oracle, Derby, or Microsoft SQL Server, there won’t be much of a
difference because you won’t be getting into any of the more advanced features of the
RDBMS engine.
Designing the Database
Now that you have things set up, let’s think about the design of your database. Like I
mentioned at the beginning of the chapter, this is a game review system. It will show off
how to do a bunch of techniques in Facebook to give you a good idea of how to use these
features in your own application.
To begin your design, you’ll need a table that holds review data. This table will hold a
user ID (UID), the game being reviewed, a rating, and a generated primary key for
convenience. You also need a game table to link to the review table that includes a game
title, publisher, ESRB rating, game genre, and release year.
If you were developing this from scratch, you would use another table to record
usernames, e-mail addresses, passwords (with some type of obfuscation in place), and other
information such as names, addresses, and so on. Since Facebook takes care of all of this,
the only information you really need from the user is the uid token in fields that will need
any type of personal information for users. Just to reiterate, it’s a good idea to keep as little
personal information about your users as needed and use Facebook methods to return the
information needed (such as usernames, where they’re at, and so on) instead of storing these
yourself. First, you could run afoul of Facebook’s terms of use, but more than that, you
waste development cycles implementing things that have already been developed.
94 Building a Facebook Application, Start to Finish
For a more formal view of your database at this point, take a look at it in the entity
relationship (ER) model shown in Figure 4-18.
Figure 4-18. First game review ER diagram
ER diagrams provide a nice visual for your design to help you walk through some of the
complexities of your design. Now that you have defined a couple of tables and a relation
(the diamond), let’s translate that into Data Definition Language (DDL) for MySQL. Figure
4-18 will translate into a slightly different table structure than I described earlier.
To create the table for games, you get the following:
CREATE TABLE game (
 game_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
 game_title VARCHAR(255) NOT NULL,
 esrb_rating VARCHAR(45) NOT NULL,
 release_year INTEGER UNSIGNED NOT NULL,
 publisher VARCHAR(45) NOT NULL,
 added TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
 asin CHAR(10) DEFAULT '' NOT NULL,
 PRIMARY KEY (game_id)
);
And here’s the table for reviews:
CREATE TABLE review (
 review_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
 uid BIGINT UNSIGNED NOT NULL,
 rating TINYINT UNSIGNED NOT NULL,
 review TEXT,
 game_id INTEGER UNSIGNED NOT NULL,
Building a Facebook Application, Start to Finish 95
 date_submitted TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
 PRIMARY KEY (review_id),
 FOREIGN KEY (game_id) REFERENCES game (game_id)
);
To take care of the game_review relation, I added the review_id tuple (column or field) to
relate the game records to individual reviews. The timestamp tuples (added and
date_submitted) will be used to display the most recently added games and reviews
somewhere on your application. There’s also a foreign key constraint on the review table
since you don’t want reviews for nonexistent games!
Working with SQL
Let’s commit your DDL to your database now. Since you’ve already installed the DPT
plug-in, all you have to do is launch the previous script in the SQL editor. You’ll create a
new SQL file with a connection to your database to insert the data. You’ll also include
some default data, just for testing purposes.
To add the new SQL file, switch to the Database Development view and select New >
SQL File, or select New > Other > SQL Development > SQL File. Give your file a name
(such as facebook_app), and set your connection information that you set up earlier (the
database server type is MySql_5.1, the connection profile name is your connection profile,
and the database name is your database name). Then click Finish.
Next, simply type the earlier code (or copy and paste it) into the file, and save it. To add
the tables, add Go between the SQL statements, right-click, and select Execute All. Check
with your favorite tool to see whether the tables were created properly.
It’s time for some dummy data so you can have something in the database. For your
games, you’ll use some of the best games of all time. You can either create a new file or
just paste these lines into the SQL file you’ve already created:
INSERT INTO game(game_title, esrb_rating, release_year, publisher)
VALUES("Super Mario Brothers","not rated",1995,"Nintendo");
INSERT INTO game(game_title, esrb_rating, release_year, publisher)
VALUES("Resident Evil 4","M",2005,"Capcom");
INSERT INTO game(game_title, esrb_rating, release_year, publisher)
VALUES("Final Fantasy III","E10+",1994,"Square");
INSERT INTO game2(game_title, esrb_rating, release_year, publisher)
VALUES("The Legend of Zelda: A Link to the Past","E",1992,"Nintendo");
96 Building a Facebook Application, Start to Finish
INSERT INTO game(game_title, esrb_rating, release_year, publisher)
VALUES("Super Metroid","E",1994,"Ninetendo");
INSERT INTO game(game_title, esrb_rating, release_year, publisher)
VALUES("Half-Life 2","M",2004,"Vivendi Games");
INSERT INTO game(game_title, esrb_rating, release_year, publisher)
VALUES("Super Mario 64","E",1996,"Nintendo");
INSERT INTO game(game_title, esrb_rating, release_year, publisher)
VALUES("The Legend of Zelda: Ocarina of Time","E",1998,"Nintendo");
INSERT INTO game(game_title, esrb_rating, release_year, publisher)
VALUES("Civilization II","E",1996,"Microprose");
INSERT INTO game(game_title, esrb_rating, release_year, publisher)
VALUES("Tetris","E",1989,"Nintendo");
INSERT INTO game(game_title, esrb_rating, release_year, publisher)
VALUES("Halo 3","M",2007,"Microsoft/Bungee");
And here’s some data for the reviews (you can change 7608007 to your own uid):
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 5, 1, 'I grew up on this game!!!');
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 4, 1, 'This game made me drop out of school!');
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 1, 1, "I wasn't even born when this came out!");
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 4, 2, 'Great game play');
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 3, 3, 'Team fighting is fun!');
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 4, 4, 'Save Hyrule from Gannon');
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 5, 5, 'Spoiler...Samus is a girl!');
Building a Facebook Application, Start to Finish 97
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 5, 6, "Gordon just can't seem to catch a break.");
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 5, 7, 'First Mario Brothers in 3D
 -- can you get the rabbits outside the castle?');
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 5, 8, 'Gannon is back!');
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 1, 9, 'I blame Sid Meier for my F in Calculus');
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 1, 10, 'Simple puzzle...hours-o-fun!');
INSERT INTO review(uid, rating, game_id, review)
VALUES (7608007, 1, 11, 'Crush the Flood!');
Now you have some data in your database that you can play with. If you query the data
(with SELECT * FROM game;), you will be able to see the games you just inserted (likewise for
the review table).
Jumping In
I’m a fan of iterative development, and since you have a table structure and an application
set up, in this section you’ll get the application to do something. For this iteration, you’ll
add some basic functionality such as the ability to view, add, and publish game reviews. For
your initial view, you’ll develop a page that will list recently reviewed games and have a
logical navigation to add reviews and ratings.
For your index page, you’ll set up some CSS for your entire site and some basic FBML
for interacting with users. For your style sheet, you’ll use a trick to include the style file
with a require_once statement. You’ll also set up some basic CSS styles to hold different
boxes to hold content areas. You need to make your style sheet file for your site in a folder
named style.
The WTP plug-in you installed when you added the PDT plug-in includes a CSS editor,
so to create a new CSS file, you simply right-click in the navigation panel, and select New
> CSS (see Figure 4-19).
98 Building a Facebook Application, Start to Finish
Figure 4-19. New CSS file


You don’t have to make all the styles since Facebook takes care of many of these for
you. However, for these purposes you’ll develop your own. First, you need to provide some
padding around your content, add a few Facebook-style boxes for your content, and add a
wide left column and smaller right column for your containers.
You’ve already added some games into your database (some of my all-time favorites
including Super Mario Brothers, Civilization II, The Legend of Zelda, and Half Life 2).
Having placeholder data is really helpful in planning how the data will be viewed on the
page, so the more data you have, the better.
You’ll make your application better, but for the time being, your PHP calls to the
database are in the index file. First for your box model, you wrap your content in a <div>
tag, with an id of body. Next, for your canvas page, you want to have a wide left column
(left-wide) and a small right column (right-small). Keeping with the general look and feel
of the Facebook web site, you’ll also have a few classes dedicated to displaying the header
information in a consistent manner.
Using your PHP template, you produce the following for an initial view of your data:
Building a Facebook Application, Start to Finish 99
<?php
/**
* File: index.php
* Description: The index file of the application
 */
require_once('config/config.inc.php');
$conn = mysql_connect($database_server, $database_user, $database_password);
@mysql_select_db($database_name);
$review_sql = 'SELECT g.game_title, r.review_id, r.date_submitted,
 r.uid, review_counter.review_total
 FROM review r, game g,
 (
 SELECT count(*) AS review_total FROM review
 ) AS review_counter
 WHERE r.game_id = g.game_id
 ORDER BY date_submitted DESC
 LIMIT 5';
$recent_reviews = mysql_query($review_sql);
$review_count = mysql_fetch_row($recent_reviews);
$games_sql = 'SELECT * FROM game g ORDER BY added DESC LIMIT 5';
$recent_games = mysql_query($games_sql);
?>
<style>
<?php require_once('style/style.css'); ?>
</style>
<div id="body">
 <div id="left-wide">
 <div id="reviews">
 <!-- recent reviews --
100 Building a Facebook Application, Start to Finish
 echo(' Reviews');
 ?>
 </div>
 <div class="right">
 <a href="reviews.php">See all reviews</a>
 </div>
 </div>
 <div class="reviews box clearfix ">
 <?php
 while ($row = mysql_fetch_assoc($recent_reviews)) {
 echo('<div class="review clearfix">
 <h3 class="review_title">
 <a href="review.php?review_
 id=' . $row['review_id']. '">'.
 $row['game_title'] .
 '</a>
 </h3'
 );
 echo('<p class="more_info clearfix">Submitted ' .
 $row['date_submitted'] . '</p></div>');
 }
 ?>
 </div>
 </div>
 </div>
 <div id="right-small">
 <div class="box">
 <h2 class="header">recently added games</h2>
 <div class="subheader clearfix">
 <h3 style="float:right;">
 <a href="games.php">See all games</a>
 </h3>
 </div>
 <div class="clearfix">
 <?php
 while($row = mysql_fetch_assoc($recent_games)){
 echo('<h3 class="game_info clearfix">
 <a href="game.php?game_id=' . $row['game_id'] .'">'
 . $row['game_title'] .
Building a Facebook Application, Start to Finish 101
 '</a></h3>');
 }
 ?>
 </div>
 </div>
 </div>
</div>
You now have the initial design laid out, but you’re also going to need some styles:
#body {
 padding: 10px;
}
#left-wide{
 width: 406px;
 float: left;
}
#right-small {
 width: 210px;
 float: right;
}
.reviews{
 border-color:#EEEEEE;
 padding:7px 8px;
}
.review{
 border-color: #ccc;
 border-bottom:1px solid #CCCCCC;
 width: 100%;
}
.header {
 background: #D8DFEA none repeat scroll 0%;
 border-top: 1px solid #3B5998;
 margin: 0px;
 padding: 2px 8px;
}
.subheader {
 background: #eee none repeat scroll 0%;
102 Building a Facebook Application, Start to Finish
 border-top: 1px solid #ccc;
 font-size: 12px;
 margin: 0px;
 padding: 2px 8px;
}
.subheader h3 {
 font-size: 11px;
 font-weight: normal;
}
.game_info {
 border-bottom:1px solid #ccc;
 float:left;
 padding:10px 10px 5px;
 width:170px;
}
.box {
 margin-bottom: 10px;
}
.more_info {
 float: left;
 padding-right: 10px;
 width: 340px;
}
.left{float:left}
.right{float:right}
If everything has gone correctly, you should now have something along the lines of
Figure 4-20.
Building a Facebook Application, Start to Finish 103
Figure 4-20. Initial Facebook view
Now that you have something up and running, you can deal with a few other initial
details. For example, you need some type of method for users to actually add games and
reviews to your application. For the purposes of this example, you’ll write these as new
pages that perform several different actions (list all the games/reviews, display individual
games/reviews, and add a game/review).
Since there is a dependency on the existence of a game in the review table, let’s start
with the games page. You’ll declare an action variable to control what is shown on the
page, and then you’ll use library functions to actually grab data for you. For the most part,
I’m using the same conventions used by Facebook coders for consistency’s sake.
Since you want to implement some code reuse, you’ll first create a new file in the lib
folder called dbmanager.php. You’ll add useful functions to get data from your database
here, along with some useful parameterization. The first thing you want to do is add some
database configuration details to your config.inc.php file to store your database
configuration details. At the end of the PHP file, add this section:
/************************* Database Settings *****************************/
$database_server = '<your_db_server>';
$database_user = '<your_db_user>';
$database_password = '<your_db_password>';
$database_name = '<your_db>';
$conn = mysql_connect($database_server, $database_user, $database_password);
@mysql_select_db($database_name);
104 Building a Facebook Application, Start to Finish
This established a database connection that you can use to globally refer to other code
segments in your application. Next you’ll create a new PHP file as before in the lib folder
named dbmanager.php. The first function you’ll define is named query, which returns the
results from your MySQL server for a given SQL command.
function query($sql){
 global $conn;
 return mysql_query($sql, $conn);
}
Now, you’ll add the different queries you’ve already written. As with your main index
page, you have a few queries that you can put into your dbmanager file so you can reuse
these on different pages. These include the recent_reviews, review_count, game_count, and
recent_games queries:
function get_recent_reviews($count){
 $query = query(sprintf('SELECT g.game_title, r.review_id, r.date_submitted,
 r.uid, review_counter.review_total
 FROM review r, game g,
 (SELECT count(*) AS review_total FROM review)
 AS review_counter
 WHERE r.game_id = g.game_id
 AND 1
 ORDER BY date_submitted DESC
 LIMIT %d', $count));
 return $query;
}
function get_review_count(){
 $query = query(sprintf('SELECT count(*) AS total_count FROM review'));
 if($row = mysql_fetch_assoc($query)){
 return $row['total_count'];
 }else {
 return 0;
 }
}
function get_game_count(){
 $query = query(sprintf('SELECT count(*) AS total_count FROM game'));
 if($row = mysql_fetch_assoc($query)){
Building a Facebook Application, Start to Finish 105
 return $row['total_count'];
 } else {
 return 0;
 }
}
function get_recent_games($count){
 $query = query(sprintf('SELECT *
 FROM game
 ORDER BY added DESC
 LIMIT %d', $count));
 return $query;
}
You’ll notice in this code that you parameterize the input through the sprintf function,
just to keep those hackers a little more honest. Each of these will return a mysql_result
object. You use these as you would any other mysql_result object with normal loop
constructs. Let’s update the code on your main index page to use these new functions. Just
use the require_once construct to include the dbmanager.php file. Now, return to the
index.php file where you have defined the call to the MySQL file, and replace the contents
of the file with calls to these functions:
<?php
/**
* File: index.php
* Description: The index file of the application
 */
require_once('config/config.inc.php');
require_once('lib/dbmanager.php');
$recent_reviews = get_recent_reviews(5);
$review_count = get_review_count();
$recent_games = get_recent_games(5);
$game_count = get_game_count();
?>
Since you used the same variable names, the rest of the code on the page doesn’t
change, and you have cleaner code.
Now let’s create a couple of functions to retrieve game information. You want to be
able to deal with all games and a single game, so you’ll create two more functions in the
106 Building a Facebook Application, Start to Finish
dbmanager.php file to deal with each of these cases. The get_all_games function will take no
parameters, and the get_game function will require a game_id parameter.
function get_all_games(){
 $query = query(sprintf('SELECT * FROM game ORDER BY added DESC'));
 return $query;
}
function get_game($game_id){
 $query = query(sprintf('SELECT * FROM game WHERE game_id = %d', $game_id));
 return $query;
}
Now that you can actually get some data from your database, let’s make some displays
in the games.php file. You create this file with the same procedure as before. The code will
be a bit more complicated, so let’s deal with displaying all_games first. In your games.php
file, let’s declare a variable $action that will tell the script what to do and then add skeleton
if/else if statements.
<?php
/**
* File: games.php
* Description: Page for handling games
 */
require_once('config/config.inc.php');
require_once('lib/dbmanager.php');
if(isset $_REQUEST('action'){
 $action = $_REQUEST('action');
} else {
 $action = 'showall';
}
?>
<style>
<?php require_once('style/style.css'); ?>
</style>
<div id="body">
<?php
Building a Facebook Application, Start to Finish 107
if($action == 'display'){
 // show all games in the collection
} else if($action == 'add'){
 // form to add new game
} else {
 // show all games in the collection
}
?>
</div>
For your default action (that displays all the games), you’ll simply call the
get_all_games function from your dbmanager.php include file and do some formatting. Insert
the following code in the else block of the if($action == 'showall') statement:
} else {
 $all_games = get_all_games();
 print('<div id="games">');
 while ($row = mysql_fetch_array($all_games)){
 $game_rating = get_game_rating($row['game_id']);
 $title = $row['game_title'];
 $game_id = $row['game_id'];
 $publisher = $row['publisher'];
 $year = $row['release_year'];
 $rating = $row['esrb_rating'];
 $added = date('d M, Y', strtotime($row['added']));
 echo <<<EOT
<div class="game">
 <div class="game_about">
 <p class="game_header">
 <a href="games.php?game_id=$game_id&action=display">
 $title
 </a>
 by $publisher ($year)
 </p>
 <p><strong>ESRB Rating:</strong> $rating</p>
108 Building a Facebook Application, Start to Finish
 <p><strong>Added:</strong> $added</p>
 <p><a href="games.php?action=display&game_id=$game_id">see reviews</a></p>
 </div>
 <div class="bumper" />
</div>
EOT;
 }
 print('</div>');
}
You’ll notice here I’m using heredoc notation to save some typing. You could have also
used print or echo, but I find that heredoc is far easier to read, especially when writing a
block of output. You’ll also notice that I added a few new classes to the style sheet.
#games {
 padding: 10px;
}
.game {
}
.bumper {
 background:#D8DFEA none repeat scroll 0%;
 border:medium none;
 color:#D8DFEA;
 height:1px;
 margin-bottom: 21px;
 overflow:hidden;
 clear: both;
}
.game_header {
 font-size: 13px;
}
.game_header a{
 font-weight: bold;
}
Now, if you navigate to the games web page, you’ll see something along the lines of
Figure 4-21.
Building a Facebook Application, Start to Finish 109
Figure 4-21. Listing of games
110 Building a Facebook Application, Start to Finish
Adding an average rating and the number of reviews for each game is also very easy.
Just write a new function in dbmanager.php to grab the information from the database for
each of the elements:
function get_game_rating($game_id){
 $query = query(sprintf('SELECT avg(rating) AS game_rating
 FROM review WHERE game_id = %d', $game_id));
 if($row = mysql_fetch_assoc($query)){
 return round($row['game_rating']);
 } else {
 return 0;
 }
}
function get_game_review_count($game_id){
 $query = query(sprintf('SELECT count(*) AS review_count
 FROM review WHERE game_id = %d', $game_id));
 if($row = mysql_fetch_assoc($query)){
 return $row['review_count'];
 } else {
 return 0;
 }
}
Your display should now incorporate this new data, but wouldn’t it be nice if you could
incorporate those little rating stars instead of having a number? The get_game_rating
function returns a rounded average, so you just need to get some stars. I made my own stars,
but if you don’t know how to do this, there are plenty of tutorials online (just Google star
rating tutorial). The basic idea here is that a rating can be from 0 (not rated) to 5 (the
highest rating). You make a file for each of these, and you basically just use the <img>
FBML tag. Remember, the <img> tag in Facebook requires an absolute reference; no relative
URLs are allowed. In other words, you must put the entire path to your image, as in
http://www.foobar.com/facebook/images/1.png.
External Web Services
Another nice feature you might want to include is pictures of the covers for the different
games you’re reviewing. Fortunately, you don’t have to store these images yourself; you
can use Amazon’s Amazon Web Service (AWS) to pull the appropriate images into your
application. To use this great service, you’ll need an AWS access key from Amazon. If you
Building a Facebook Application, Start to Finish 111
don’t already have one, you can sign up at http://aws.amazon.com/. I’ll cover joining the
associate program in the next chapter, but for the time being, you just need an AWS access
key.
Since you’ll probably want to use this on many pages, make a global variable for the
key in the config.inc.php file:
/*********************** Amazon Settings ***************************/
$amazon_key = '<your_amazon_aws_key>';
Now you’ll create a new file named amazon.php in your lib folder to handle your calls to
Amazon’s web service. This is a very basic class object that will work through Amazon’s
REST protocol to query specific XML responses.
<?php
class AmazonClient {
 public $amazon_key; // AWS key
 public $amazon_associate; // associate id, if you have one
 public function __construct($amazon_key, $amazon_associate=''){
 $this->amazon_key = $amazon_key;
 $this->amazon_associate = $amazon_associate;
 }
 /**
 * Simple REST client for Amazon AWS
 * @param $params Query parameters to pass to AWS
 * @return SimpleXML object of the REST response
 */
 function amazon_search($params){
 $url = $this->build_query($params);
 $response = file_get_contents($url);
 $xmlObject = simplexml_load_string($response);
 return $xmlObject;
 }
 /**
 * Function to build query string for AWS
 * @param $params search parameters to pass to AWS
 * @return AWS REST query URL string
 */
112 Building a Facebook Application, Start to Finish
 function build_query($params){
 $constants = array('Service' => 'AWSECommerceService',
 'SubscriptionId' => $this->amazon_key,
'AssociateTag' => $this->amazon_id,
'SearchIndex' => 'VideoGames');
 $query_string = '';
 // add params to search string
 foreach($constants as $key => $value){
 $query_string .= "$key=" . urlencode($value) . "&";
 }
 // add searchparams to search string
 foreach($params as $key => $value){
 $query_string .= "$key=" . urlencode($value) . "&";
 }
 return = 'http://ecs.amazonaws.com/onca/xml?' . $query_string;
 }
 /**
 * Return an array of the images (small, medium,
 * and large) for a given ASIN
 * @param $asin The ASIN number to search
 */
 function get_game_image($asin){
 $params = array( 'Keywords' => $asin,
 'Operation' => "ItemSearch",
'ResponseGroup' => 'Images' );
 $xml = $this->amazon_search($params);
 $results = array();
 foreach($xml->Items->Item as $item){
 $results['small_url'] = $item->SmallImage->URL;
 $results['small_height'] = $item->SmallImage->Height;
 $results['small_width'] = $item->SmallImage->Width;
 $results['medium_url'] = $item->MediumImage->URL;
 $results['medium_height'] = $item->MediumImage->Height;
Building a Facebook Application, Start to Finish 113
 $results['medium_width'] = $item->MediumImage->Width;
 $results['large_url'] = $item->LargeImage->URL;
 $results['large_height'] = $item->LargeImage->Height;
 $results['large_width'] = $item->LargeImage->Width;
 }
 return $results;
 }
}
?>
Tip ➡ Not sure what’s needed in your AWS call? There’s a great online resource at
http://www.awszone.com that lists all the fields you can search for a given search type. If you run into
problems, just fill out the form and see what needs to be in your URL when searching the AWS servers.
Now, all you need to do is include the class, instantiate the object, and call the
get_game_image method. But wait…that method requires a field called ASIN that you
haven’t added to your database. Let’s commit this new tuple to the game table and work on
fixing what you have so far.
First you’ll add the field to the database using the Database Development tool. If you
open the SQL file you created earlier (or a new one) and set your connection information,
you may notice that your database isn’t selected. To see your database, you have to connect
to the database system. You can do this by switching to the Database Development view,
right-clicking your database instance, and selecting Connect (see Figure 4-22).
114 Building a Facebook Application, Start to Finish
Figure 4-22. Reconnecting to your database back end
Once you have an SQL file open, modify the table definition with this:
ALTER TABLE game ADD COLUMN asin VARCHAR(30) NOT NULL AFTER release_year;
This adds the new ASIN tuple into to the database, but you still need to get the ASINs
(where they exist) for the rest of the games. For convenience, I looked these up already, and
you can just update the game table with the following. We’ll deal with looking up ASINs
when new games are added.
UPDATE game SET asin = 'B0001ZZNNI' WHERE game_id = 1;
UPDATE game SET asin = 'B000B69E9G' WHERE game_id = 2;
UPDATE game SET asin = 'B000GABOTU' WHERE game_id = 3;
UPDATE game SET asin = 'B000B69E9G' WHERE game_id = 4;
UPDATE game SET asin = 'B00002STXN' WHERE game_id = 5;
UPDATE game SET asin = 'B00002SVFV' WHERE game_id = 6;
UPDATE game SET asin = 'B000ID1AKI' WHERE game_id = 7;
UPDATE game SET asin = 'B00000DMB3' WHERE game_id = 8;
UPDATE game SET asin = 'B000FPM8OG' WHERE game_id = 9;
UPDATE game SET asin = 'B000W1XGW6' WHERE game_id = 10;
Building a Facebook Application, Start to Finish 115
UPDATE game SET asin = 'B000FRU0NU' WHERE game_id = 11;
I like how Amazon displays its images, so let’s put the small image from AWS on the
games page. Now, include the new Amazon page, and call the code:
$require_once('lib/amazon.php');
$amazon = new AmazonClient($amazon_key);
$images = $amazon->get_game_image($row['asin']);
// make sure a structure was returned
if(sizeof($images) > 0){
 $image = $images['small_url'];
 $img = '<img src="' . $image . '" />';
} else {
 $img = 'No Image Available';
}
Now you just need to edit the heredoc string to include a new <div> for the image in the
games.php file:
<div class="game_image">
 $img
</div>
Lastly, add a bit of CSS to define the game_image style and then update the game_about
style to clear the image style:
.game_image {
 float: left;
}
.game_about {
 margin-left: 60px;
}
Let’s take a look at your work now. If everything has gone to plan, you should now
have something that looks like Figure 4-23.
Figure 4-23. Games view with images Game Review You’re quickly getting a useful application together. Now you’ll build the individual game review page. You need to write a new query to get all the reviews with a specified game_id. In the dbmanager.php file, add the following function: function get_game_reviews($game_id){ $query = query(sprintf('SELECT * FROM review r WHERE game_id = %d ORDER BY date_submitted DESC', $game_id)); return $query; } Building a Facebook Application, Start to Finish 117 This function simply gets all the information from the review table for the game_id. Since you have constructed the URL for the action already, you can grab the actual game information as you did in the previous loop structure by including the following code in the games.php file: if(! isset($_REQUEST['game_id'])){ $_REQUEST['game_id'] = 1; } $game_id = $_REQUEST['game_id']; $game = get_game($game_id); $game_rating = get_game_rating($game_id); $game_reviews = get_game_reviews($game_id); $title = $game['game_title']; $game_id = $game['game_id']; $publisher = $game['publisher']; $year = $game['release_year']; $rating = $game['esrb_rating']; $added = date('d M, Y', strtotime($game['added'])); $game_rating = get_game_rating($game_id); $review_count = get_game_review_count($game_id); $amazon = new AmazonClient($amazon_key); $images = $amazon->get_game_image($game['asin']); if(sizeof($images) > 0){ $image = $images['medium_url']; $img = '
$img
Rating: $game_rating ($review_count total reviews)
ESRB Rating: $rating
Added: $added
EOT; This gives you the primary game description (along with a new offset style class that sets the left margin of the information to 160 pixels since we’re using the medium-sized image), so let’s take it a step further and add the review information. You’ll style the reviews basically like a wall, with newer posts at the top: print('
'); while($row = mysql_fetch_assoc($game_reviews)){ $uid = $row['uid']; $rating = $row['rating']; $review = nl2br($row['review']); $submitted = strtotime($row['date_submitted']); $time = date('h:ia', $submitted); $date = date('d M, Y', $submitted); $stars = '/images/' . $rating . '.png'; echo <<< EOT
reviewed Building a Facebook Application, Start to Finish 119 $title
at $time on $date
$review
EOT; For the reviews, this code used the and to pull in user data (including links to the user profiles). You could have made a more sophisticated FQL query to find the user’s information (name and picture), but using the tags is far more efficient, especially since these tags were designed specifically to do what you’re doing here. Add Game The last thing you need to do for this page is allow people to add new games to your application, so here you’ll start coding the “add” section. For this action, you’ll use MockAjax to add information to the form. You could also use the tag (or just a plain old HTML form), but the MockAjax facilities for adding a modal dialog box are nice to work with. You’ll be nesting your form within the tag. The nice part about this is that you can put this anywhere on your page, and it will be hidden until someone clicks an action item (for example, a hyperlink) that has a clicktoshowdialog attribute. You’ll then use the power of FBJS to insert the information into the database and refresh the game page. To start, you’ll add a couple of links inside the body
. The first one just returns you to the default view, and the other sets up the call to the dialog box. In the body
, add the following lines: all games add game Now you’ll add the actual dialog box that get called when the user clicks the Add Game link:
120 Building a Facebook Application, Start to Finish
Game Title:
Publisher:
Year Released:
Rating:
Because you’re using the tag, the form will be shown only when the user clicks the Add Game hyperlink. You pass the entire form a new page (add_game.php) that contains the logic to add games to the application by referencing the form_id in the tag. The code in add_game.php will handle looking up the ASIN of the game from Amazon, inserting the data, and redirecting the user to the games.php page with a status message. You’ll need to add a couple of functions in the dbmanager.php and AmazonRestClient code. In the AmazonRestClient, you need a function that will look up an ASIN for a given title. In the dbmanager.php code, you have a couple of functions, one to tell you whether a given title has already been inserted in the database and one to insert data into the database. Building a Facebook Application, Start to Finish 121 To write the ASIN lookup, you need to retrieve information for a title lookup. This will be a fairly basic lookup where you assume that the first result passed back from Amazon is the correct title the person was inserting. In a more sophisticated application, you want to present the results to the user to let them choose which title they actually wanted. function asin_lookup($title){ $params = array('Title' => $title, 'Operation' => 'ItemSearch', 'ResponseGroup' => 'ItemAttributes'); $xml = $this->amazon_search($params); $xml_result = $xml->Items->Item; return $xml_result->ASIN; } Now all that is left is a little checking in the add_game.php page to make sure everything went OK. First, you want to make sure that the game title doesn’t exist in the database, and then you look up the ASIN and insert the new game record into the database: if(isset($_REQUEST['game_title'])){ $game_title = $_REQUEST['game_title']; $type = "error"; if(game_exists($game_title)){ // check to see if the title exists $message = "Sorry, looks like " . $game_title . " is already in our database"; } else { // check in Amazon $amazon = new AmazonClient($amazon_key); $asin = $amazon->asin_lookup($game_title); if(strlen($asin) > 0){ // double-check this in the database if(game_exists_asin($asin)){ $message = "Sorry, looks like " . $game_title; $message += " is already in our database"; } else { add_game($_REQUEST['game_title'], $_REQUEST['publisher'], 122 Building a Facebook Application, Start to Finish $_REQUEST['release_year'], $_REQUEST['esrb_rating'], $asin); $message = $_REQUEST['game_title'] . " was successfully added"; $message += " to the database. Please be sure to write a review!"; $type = "success"; } } else { $message = "Sorry, couldn't find " . $_REQUEST['game_title']; $message += " at Amazon."; } } echo(''); } This code will return a status message in the games.php page that lets the user know whether a game was added, as well as other information. If a new game was successfully added, that fact is sent to the user’s profile, and the user is then redirected to the games.php page. The last thing you want to do at the top of the games.php page is display the message from the add_game.php code. Just under the navigation in games.php, add this code to display the messages: '); } else { echo(''); } } ?> This is just a nice way to give the user a little feedback on successful/unsuccessful actions. You’ve done the heavy-lifting for your application; now the reviews are a piece of cake. I won’t go into great detail for this since I’ve covered most of the techniques before. Instead of filling these pages with code, I’m certain you can write the rest of the code for this application. Building a Facebook Application, Start to Finish 123 Publishing Feeds Now that you have a functioning application, one further improvement is to publish the actions to the user’s profile. There are really two way you can do this. The first is to publish to the individual’s feed, and the other is to publish to the user’s friends’ feeds. The fun part is to use feed.publishTemplatizedAction to publish a templatized action to the user’s feed. For any action you want to immortalize in your user’s feed, simply call the feed_publishTemplatizedAction function from the FacebookRestClient object: $title_template = '{actor} added {game} to MyTestApp'; $title_data = '{"game":"' . $game_title .'"}'; $facebook->api_client->feed_publishTemplatizedAction($title_template, $title_data, '', '', ''); I especially like to publish feeds this way because the feed preview from the Facebook tools (http://developers.facebook.com/tools.php?feed) gives you a lot of help in testing how the feed will look. The big thing to remember is that you need to have {actor} somewhere in the $title_template variable so Facebook knows where to place the proper username in the text. This tag did go through a recent change, so make sure you take a look at the most recent wiki documents for the latest on this tag. Testing You’ll need to create a new account (not your real account) on Facebook and then register that account as a test user at http://www.facebook.com/developers/become_test_account.php. You’ll need an e-mail address for this account to work, so you can create one at Google, Yahoo, or MSN, or you can create e-mail aliases with a service such as MailExpire (http://www.mailexpire.com/). You should remember that test users aren’t “real” Facebook users, so they won’t see the “real” people on the network. Also, you can’t set a test account to be the application owner. You most likely need only one of these accounts to test your application (or ask a good friend). However, this doesn’t actually provide you with any real human input. If you want to get some “real” people to give you some feedback, there’s a channel in the forums to do this (http://forum.developers.facebook.com/viewforum.php?id=16). Remember, these folks are volunteering their time to give you feedback. If their feedback isn’t what you’re expecting, remember to stay positive because we’ve all seen forums degrade quickly into name calling. 124 Building a Facebook Application, Start to Finish Debugging So, what if you run into a problem and something just isn’t displaying properly in your application? There are a bunch of tools that can help. Chief among these are the error messages that you get on your page. In case you’ve forgotten a = or ; in your code, you can at least see the line that you need to check. Another handy tool is the Firebug extension for Firefox (http://www.getfirebug.com/), especially if you’re working with FBJS and MockAjax. The JavaScript console can give you important details on what’s going on, plus it’s great for dissecting code and CSS. If you don’t already have it, I highly recommend downloading this extension ASAP! Facebook also has tools to help you isolate your code and test it. The Tools page on the Facebook Developers web site (http://developer.facebook.com/tools.php) has several tools that are useful in figuring out (and testing) how code will look/function in the wild. If you still are running into problems, you can turn to the Facebook forums (http://forum.developers.facebook.com/). You can search for your particular problem or start a new thread. There are also IRC channels for chatting with other Facebook developers (such as #Facebook on freenode). More often than not, someone hanging out in one of these areas can at least point you in the correct direction. Remember, be clear and concise when you’re describing your problem; subjects like “My app is broken” probably won’t get much helpful feedback. Scaling So, what happens when you write an application that has 500,000 installations and huge bandwidth constraints? I hope you’ve placed some ads somewhere that will offset your server costs, or you may get kicked off your server host. Watch your apps, and if you need to get more bandwidth, see whether your provider has larger plans. Not that this is necessarily an endorsement, but Joyent recently announced a deal to provide its Accelerator service free for one year to Facebook developers (http://www.joyent.com/developers/facebook). Its basic service offers at least one processor and 512 megabytes of RAM with 10GB of storage with no bandwidth restrictions. There is a waiting list now, but it is an option to get you off the ground. If you outgrow these parameters, there are also plans starting at $45/month. Again, I can’t stress this enough: if your application doesn’t have the capacity to grow with your users, people will start removing your application, and no one wants that to happen! Building a Facebook Application, Start to 

No comments