So my investigation of the Heroku platform failed at the database access point. Though Heroku supports PHP it does not support the mysqli class and therefore cannot be used for my PHP/MySQL project :( Unless I switch to Ruby! I'm far too long in the tooth to switch development languages so the decision to ditch Heroku was made!
Before giving up completly on the distributed application model I investigated PHPfog to see if it could help where Heroku failed. The description of their services sounds wonderful and exactly what I would need, basically an abstracted PHP environment distributed ontop of an Amazon Cloud EC2 backbone. However, when I created a test application in their "shared cloud" environment it failed to ever complete its initial configuration. So, yeah, its broken! lol
All of this effort and time investigating distributed applications was really just my typical "path of least resistance" mentality and my general fear of maintaining Linux servers. However, it simply cannot be avoided. The level of control and removal of the "middle man" makes the best financial sense and leaves me with the most control over my application.
So back to the Amazon AWS services I went to investigate topologies for my application. In my search I found this very useful link describing the implementation of a Facebook stack right in the AWS Dashboard: http://aws.amazon.com/articles/1044
This page shows the ideal topology for a Facebook app:
Looking at this picture made me realize a fundamental flaw in how I delivered Cruise Time. Cruise Time operated on a single EC2 instance which had the PHP application and executable .SWF file on it. As the game grew we only increased the size of the ECU to scale to demand. Since the game peaked at only 125,000 users it never stressed out the single EC instance.
To distribute this across many multiples of EC2 instances in a high traffic situation would require the entire EC2 image to be saved as AMI and allowed to scale within the Auto Scaling Group in the picture above.
So the new approach would have to divorce as much as possible from the scalable EC2 instances so they can be scaled on demand and put the deliverables off in their own space. That's S3 in Amazon parlance, their file storage cloud. Putting music files, the game executable, and other data files on S3 would allow the PHP application to swing freely with scalable demand while reading the executable from S3 at a known location.
What this does is allows me to push new code changes in the EXE/SWF straight to S3 without having to go and modify the AMI for the EC2 instances or some other crazy live-update scheme on running EC2 instances of the application.
The down side is that this is not true for the PHP application. Any changes to the PHP application WOULD necessitate an update to the AMI. So now the problem becomes: how do I make the PHP application dynamic enough that changing it wont cause a lot of AMI updates or downtime on the app?
Ah the joys of software design :)

Thursday, October 6, 2011
Monday, October 3, 2011
redirect_uri gotcha!
I couldn't leave it alone! So I added the authorization code to the index.php file from my previous post. Here is the latest code:
$config = array();
$config['appId'] = $app_id;
$config['secret'] = $app_secret;
$config['fileUpload'] = false; // optional
$facebook = new Facebook($config); // constructor will start the PHP session
$user = $facebook->getUser();
if ($user) {
try {
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
} else {
//
// no user! attempt to authorize using new OAuth2.0 garbage
//
$params = array(
'scope' => 'publish_actions, email',
'redirect_uri' => 'http://apps.facebook.com/piratestradewinds/',
'canvas' => 1
);
$loginUrl = $facebook->getLoginUrl($params);
// redirect to login
echo("<script> top.location.href='" . $loginUrl . "'</script>");
}
The problem encountered when adding the code for when $user == null was in the redirect_uri parameter for the call to getLoginUrl(). The desired behavior is after the authorization, the user is redirected to your app within facebook. DO NOT use the Canvas URL but instead use the "Canvas Page" from your app's basic settings page.
AND! Don't forget the trailing slash as well else youll get the infamous "URL does not belong to your application" error from Facebook.
Now this knowledge will live forever, here, on the internet... Until Facebook changes everything AGAIN, in 2 days. Maybe they're changing it right now! /paranoia /sigh
$config = array();
$config['appId'] = $app_id;
$config['secret'] = $app_secret;
$config['fileUpload'] = false; // optional
$facebook = new Facebook($config); // constructor will start the PHP session
$user = $facebook->getUser();
if ($user) {
try {
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
} else {
//
// no user! attempt to authorize using new OAuth2.0 garbage
//
$params = array(
'scope' => 'publish_actions, email',
'redirect_uri' => 'http://apps.facebook.com/piratestradewinds/',
'canvas' => 1
);
$loginUrl = $facebook->getLoginUrl($params);
// redirect to login
echo("<script> top.location.href='" . $loginUrl . "'</script>");
}
The problem encountered when adding the code for when $user == null was in the redirect_uri parameter for the call to getLoginUrl(). The desired behavior is after the authorization, the user is redirected to your app within facebook. DO NOT use the Canvas URL but instead use the "Canvas Page" from your app's basic settings page.
AND! Don't forget the trailing slash as well else youll get the infamous "URL does not belong to your application" error from Facebook.
Now this knowledge will live forever, here, on the internet... Until Facebook changes everything AGAIN, in 2 days. Maybe they're changing it right now! /paranoia /sigh
Heroku Facebook PHP Canvas App!
Well today I decided to try my hand at launching the framework for my newest Facebook app using Facebook's new cloud computing partner, Heroku.
My apps launched to date have all been PHP/Javascript on the server side and Flash Clients. Right off the bat I realized Heroku is a Ruby on Rails shop and should have thought then "Oh I'm in for it." Apparently they made an exception for Facebook and support PHP applications, but ONLY if they are Facebook apps generated from the Facebook Developer app.
So I get started by simply following the instructions at the Facebook blog page.
This all worked flawlessly of course, if I were a Web site and not an APP! /doh So I need to modify the thing! Facebook tells me to go to Heroku's website and follow their instructions.
Following their instructions I break down at the "git clone" step of their command line interface, failing with the following:
Permission denied (publickey).
fatal: The remote end hung up unexpectedly
Wonderful! Long story short, the public key files created by the initial log on step were saved off in Users/User/.ssh and not in the /Git subdirectories. So I simply copied the private and public rsa files to Git/.ssh and it was finally able to do pushes to my new app on Heroku! Yay!
But now, on to the Facebook integration. I haven't done any Facebook coding since I first integrated Cruise Time last year so it felt like a time warp back to the desperate "oh shit" moments when I had to launch Cruise Time in 2 months and had not the faintest idea about facebook haha.
I cut and pasted alot of different, and conflicting examples from many places in Facebook's developer documentation with little success. I finally decided to stop beating around the bush and go right to the source, literally, and just headed to https://github.com/facebook/php-sdk to get the offical and latest Facebook PHP SDK. From the examples there I was able to publish my shiny new bootstrapping index.php to Heroku as follows:
<?php
// Enforce https on production
//if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == "http" && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
// header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
// exit();
//}
require_once("php-sdk/facebook.php");
$app_id = getenv('FACEBOOK_APP_ID');
$app_secret = getenv('FACEBOOK_SECRET');
$my_url = "http://pottw.herokuapp.com/index.php";
$config = array();
$config['appId'] = $app_id;
$config['secret'] = $app_secret;
$config['fileUpload'] = false; // optional
$facebook = new Facebook($config);
$user = $facebook->getUser();
if ($user) {
try {
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
} else {
$loginUrl = $facebook->getLoginUrl();
// redirect to login
}
?>
<html>
<head>
</head>
<body>
<?php if ($user): ?>
<h3>You</h3>
<img src="https://graph.facebook.com/<?php echo $user; ?>/picture">
<h3>Your User Object (/me)</h3>
<pre><?php print_r($user_profile); ?></pre>
<?php else: ?>
<strong><em>You are not Connected.</em></strong>
<?php endif ?>
</body>
</html>
But when I tried to run this, PHP threw the ol' "invalid file" error. I had copied the Facebook sdk into a subdirectory of my app tree and it was not automatically included in the commits. More web browsing and I found this gem of a resource: http://spheredev.org/wiki/Git_for_the_lazy . There I learned the command-line options to add a directory to my git source control (I'm a windows guy for 20+ years, so getting me to do command line work is really something! haha).
To my sincerest pleasure, Git was able to commit and push all of my new lovely source files, including the Facebook SDK to my shiny new Heroku app and on running it was rewarded with the output:

So there you have it. My hair-greying attempt at bootstrapping a new Facebook app. The next step is to improve the redirect logic to handle the uninstalled user and automatically perform the OAuth2.0 authentication step and then I can move on and think about a better program flow for the PHP application for my new game code-named "PvP."
My apps launched to date have all been PHP/Javascript on the server side and Flash Clients. Right off the bat I realized Heroku is a Ruby on Rails shop and should have thought then "Oh I'm in for it." Apparently they made an exception for Facebook and support PHP applications, but ONLY if they are Facebook apps generated from the Facebook Developer app.
So I get started by simply following the instructions at the Facebook blog page.
This all worked flawlessly of course, if I were a Web site and not an APP! /doh So I need to modify the thing! Facebook tells me to go to Heroku's website and follow their instructions.
Following their instructions I break down at the "git clone" step of their command line interface, failing with the following:
Permission denied (publickey).
fatal: The remote end hung up unexpectedly
Wonderful! Long story short, the public key files created by the initial log on step were saved off in Users/User/.ssh and not in the /Git subdirectories. So I simply copied the private and public rsa files to Git/.ssh and it was finally able to do pushes to my new app on Heroku! Yay!
But now, on to the Facebook integration. I haven't done any Facebook coding since I first integrated Cruise Time last year so it felt like a time warp back to the desperate "oh shit" moments when I had to launch Cruise Time in 2 months and had not the faintest idea about facebook haha.
I cut and pasted alot of different, and conflicting examples from many places in Facebook's developer documentation with little success. I finally decided to stop beating around the bush and go right to the source, literally, and just headed to https://github.com/facebook/php-sdk to get the offical and latest Facebook PHP SDK. From the examples there I was able to publish my shiny new bootstrapping index.php to Heroku as follows:
<?php
// Enforce https on production
//if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == "http" && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
// header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
// exit();
//}
require_once("php-sdk/facebook.php");
$app_id = getenv('FACEBOOK_APP_ID');
$app_secret = getenv('FACEBOOK_SECRET');
$my_url = "http://pottw.herokuapp.com/index.php";
$config = array();
$config['appId'] = $app_id;
$config['secret'] = $app_secret;
$config['fileUpload'] = false; // optional
$facebook = new Facebook($config);
$user = $facebook->getUser();
if ($user) {
try {
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
} else {
$loginUrl = $facebook->getLoginUrl();
// redirect to login
}
?>
<html>
<head>
</head>
<body>
<?php if ($user): ?>
<h3>You</h3>
<img src="https://graph.facebook.com/<?php echo $user; ?>/picture">
<h3>Your User Object (/me)</h3>
<pre><?php print_r($user_profile); ?></pre>
<?php else: ?>
<strong><em>You are not Connected.</em></strong>
<?php endif ?>
</body>
</html>
But when I tried to run this, PHP threw the ol' "invalid file" error. I had copied the Facebook sdk into a subdirectory of my app tree and it was not automatically included in the commits. More web browsing and I found this gem of a resource: http://spheredev.org/wiki/Git_for_the_lazy . There I learned the command-line options to add a directory to my git source control (I'm a windows guy for 20+ years, so getting me to do command line work is really something! haha).
To my sincerest pleasure, Git was able to commit and push all of my new lovely source files, including the Facebook SDK to my shiny new Heroku app and on running it was rewarded with the output:
You
Your User Object (/me)
Array ( [id] => 1021302301 [name] => Dean Dino Gibson [first_name] => Dean [middle_name] => Dino [last_name] => Gibson [link] => http://www.facebook.com/DrumDinoX [username] => DrumDinoX [location] => Array ( [id] => [name] => ) [bio] => The Philanthropy of Metal! Drummer/Producer for Age & Treachery by night... On-line coder-extraordinaire by day! [work] => Array ( [0] => Array ( [employer] => Array ( [id] => 140261279380556 [name] => Dracos Software ) [location] => Array ( [id] => 107602962595896 [name] => Cypress, Texas ) [position] => Array ( [id] => 108323085888596 [name] => Principal Engineer ) [description] => Independant Gaming Contractor focused on the Facebook space. [start_date] => 2011-09 [projects] => Array ( [0] => Array ( [id] => 250060951707316 [name] => Code name "PvP" ) ) ) [1] => Array ( [employer] => Array ( [id] => 105336196171423 [name] => A Little Entertainment ) [location] => Array ( [id] => 106308306067511 [name] => The Woodlands, Texas ) [position] => Array ( [id] => 108323085888596 [name] => Principal Engineer ) [with] => Array ( [0] => Array ( [id] => 1597972162 [name] => Van Collins ) ) [description] => Facebook games! [start_date] => 2010-01 [end_date] => 2011-08 [projects] => Array ( [0] => Array ( [id] => 159463290798105 [name] => Space Trader Joe [start_date] => 2011-03 [end_date] => 2011-08 ) [1] => Array ( [id] => 105315876173199 [name] => Cruise Time [start_date] => 2010-09 [end_date] => 2011-03 ) ) ) [2] => Array ( [employer] => Array ( [id] => 106032226094178 [name] => New World Computing ) [start_date] => 1998-08 [end_date] => 2003-08 ) ) [education] => Array ( [0] => Array ( [school] => Array ( [id] => 106362256066529 [name] => Point Loma Senior High ) [type] => High School ) [1] => Array ( [school] => Array ( [id] => 108727889151725 [name] => George Washington University ) [year] => Array ( [id] => 142673469093081 [name] => 1993 ) [type] => College ) ) [gender] => male [timezone] => -5 [locale] => en_US [verified] => 1 [updated_time] => 2011-09-29T15:40:25+0000 )
So there you have it. My hair-greying attempt at bootstrapping a new Facebook app. The next step is to improve the redirect logic to handle the uninstalled user and automatically perform the OAuth2.0 authentication step and then I can move on and think about a better program flow for the PHP application for my new game code-named "PvP."
Subscribe to:
Posts (Atom)