Preload FQL
From Facebook Developers Wiki
Contents |
[edit] Introduction
Let's say we're making an application that shows the interests of my friends. Not a very interesting app, but a good example. Logically, the app would have a page apps.facebook.com/interests/view.php?uid=10 that shows the interests of the user with user ID 10. Here's the flow for the app.
- A user requests this page. The request gets sent to Facebook.
- Facebook requests FBML from the application's host server.
- The application server makes an API request to Facebook, like
facebook.fql.query("SELECT interests FROM user WHERE uid=10"). - Facebook returns the data.
- The application sends FBML to Facebook.
- Facebook renders it and returns it to the user.
Phew. A lot of calls for a simple application. Let's trim it. Since we pretty much know what API call we're going to make the first time we hit Facebook, why not just send the data along the first time around? Here's the new flow:
- A user requests this page. The request gets sent to Facebook.
- Facebook requests FBML from the application server, and passes along the result of
facebook.fql.query("select interests from user where uid={*user*}"). - The application sends FBML to Facebook.
- Facebook renders it and returns it to the user.
[edit] Usage
We need some mechanism for applications to specify what query to run. We call these Preload FQL rules. They take three parts.
-
name- The name of this rule. -
pattern- A regular expression to match to the URL. -
query- A parameterized FQL query to run.
An application can set as many of these rules as they like. Here's how we process them on our side.
For each rule, if a pattern matches a URL snippet:
For instance, in our example, you may have a rule (in JSON) as:
It's that simple. To set these rules, you need to call admin.setAppProperties. Here's our PHP code.
Regarding the json_encode for the $fetch variable, admin.setAppProperties expects its arguments as strings or numbers. See ApplicationProperties for more details.
Also note there is a special parameter {*user*} that gives the active user, so if you want to get the friends of the current user who have authorized the application, try:
[edit] FBML Applications
FBML applications will receive preloaded FQL data through HTTP_POST when a page matching the pattern is loaded. The data comes to your server as a JSON-encoded post parameter named fb_sig_ + name along with other parameters, such as those listed in Authorizing Applications. Note that the contents of this parameter will also be used for validation against fb_sig.
Using the PHP client, you can preload FQL with a call to a client object's get_valid_fb_params($_POST, null, 'fb_sig') method, which should return an associative array with your preload FQL rule name as a key and result as a value. If the client method validate_fb_params() is called, preload FQL will be available through $(your client object)->fb_params[(your preload FQL rule name)].
To get the interests in PHP without using the client, we can look in _POST['fb_sig_interests']. Since PHP auto-escapes quotes in post parameters, we need to be a bit tricky.
In other languages this should be as simple as:
[edit] iframe Applications
You can use preload FQL data for iframe applications as well, in two ways. The data can be received via HTTP_POST similar to FBML applications, though this does require an additional (lightweight and cached) redirect and the POST data has a different prefix, 'fb_post_sig_' to avoid namespace collision with expected HTTP_GET parameters normally passed to iframe applications. In addition to HTTP_POST, the data can be used by the JavaScript Client Library without making additional requests or incurring additional server load.
[edit] Using with the JavaScript Client Library
A special method has been added to the JavaScript Client Library's API client to allow access to these parameters. After client initialization, a call to FB.Facebook.apiClient.preloadFQL_get(callback) will invoke the callback function with an object with rule names as parameter names and JSON-encoded query results as values for the parameters. The client library includes a utility function, FB.JSON.deserialize, that can be used to decode the values.
[edit] Posting to iframe Applications
Because you may choose to use the JavaScript client to use with iframe preload FQL and the slight overhead from a redirect with POST data, preload FQL POST to iframes is optional. To enable this behavior for any page, create an additional rule with fb_iframe_post as the name and a regular expression to match pages where this behavior is desired as the pattern.
From the above example, we could specify (in JSON):
This would make the preload FQL interests data for the JavaScript Client Library on all pages matching /view.*/ and among these pages, POST the query data to the iframe for all pages matching /viewpost.*/.
An important distinction is the change in prefix to 'fb_post_sig' for all Facebook parameters sent via POST to iframes. These can be accessed with a call to the aforementioned get_valid_fb_params($_POST, null, 'fb_post_sig') method, with the fb_post_sig prefix instead of fb_sig. Additionally, using the latest version of the PHP client, variables receiving this will automatically be in $(your client object)->fb_params[(your preload FQL rule name)] after a call to validate_fb_params().
[edit] Gotchas
- Remember: Using preloaded FQL does not make the FQL itself faster. It only cuts down the need for extra API calls and related latency.
- When you use preload FQL you no longer receive fb_sig_friends. To mimic the old behavior you can just do:{"friends" : {"pattern": ".*", "query" : "select uid2 from friend where uid1={*user*}"}}
This comes in a slightly different format. Instead of:123,323,43225,234234,...
They'll come as:[["123"],["323"],["43225"],["234234"],...]
This change should save the cost of getting fb_sig_friends on every canvas page.
[edit] Client Library Developer Note
admin.setAppProperties takes a map from keys to values where the values are strings or numbers. So to use preload FQL, you need to first encode the preload_fql structure as a string and then encode the whole property map.
For instance, this is incorrect:
But this is correct:
For further clarification, see the PHP client library.

