Installing the Facebook Open Platform
Facebook is cool. It's a little past its best now (it may be seen as 2007's YoYo) but the technology underneath it is proven, scalable and solves many of the problems any site wanting to introduce some 'magic social dust' contains.
Now, Facebook have released their Facebook Open Platform. This looks interesting. Not sure what I can do with it yet, but its a nice thing to start messing around with - particularly the FBML and FBJS implementations - FBML especially as it's a lovely thing which we can use for all kinds of simple site layout things.
It wasn't totally easy getting it up and running, but here's my method which you're welcome to follow if you'd like.
Background
I'm running Apache on CentOS with PHP 5.1.6 already installed and working with Apache. In this tutorial, I'll assume you have:- Apache 2+
- PHP 5+ working with Apache
- CentOS
- FTP/sFTP access to your server
- command line access with sudo permissions where needed (for restarting Apache and editing
httpd.conffor example) - MySQL 5+ working with PHP
Getting Started
- Grab the code from Facebook: http://developer.facebook.com/fbopen/
- Unzip
- FTP to your server and create a folder in your webroot like 'fbop'. This will be where your instace of the platform lives i.e
http://www.example.com/fbop/ - Upload the contents of the 'html' folder in the unzipped fb-open-platform folder into your new 'fbop' folder on your web server. If you now go to
http://www.example.com/fbop/fbopentest/fbml.phpyou'll see a ton of errors. That's okay, we'll fix them in a bit. - Now, choose where you want your facebook open platform libraries to live. Sensibly, this will be away from your webroot, but with all your other php libraries. I've chosen /var/www/fblib/lib. Go ahead and create this folder and upload the contents 'lib' folder from your unzipped fb-open-platform folder.
- /var/www/fblib/lib/
- api/
- common.php
- core/
- display/
- .....
- /var/www/html/fbop/
- api/
- canvas.php
- common/
- fbml/
- fbopentest/
- js/
http://www.example.com/fbop/fbopentest/fbml.phpConfiguring Apache
Facebook have been a bit wierd and rather than telling PHP where to look for includes like most apps, they've set a custom Apache variable which PHP then uses to find some files. This isn't easy info to find out by Googling, but its very simple to implement.- Open your
httpd.conffile. - At the bottom, or near your other non-standard config changes, add the line...
SetEnv PHP_ROOT "/var/www/fblib" - This sets a new variable constant in Apache called 'PHP_ROOT'. From within PHP this is now accessible using the
$_SERVER["PHP_ROOT"]variable. The lack of this variable being present was that cause of all those errors we've been seeing. - Restart Apache. For me on CentOS, this means running
$sudo /sbin/service httpd restart - You should now be able to test if this has worked by creating a new PHP file, and adding (inside you php braces, this line...
print_r($_SERVER);. Opening that in a browser will list all the server variables available to PHP. Magically, one of them should be PHP_ROOT with the value you specified earlier. This is good.
http://www.example.com/fbop/fbopentest/fbml.php will give us no errors! Sadly it won't do much else.Configuring the database
Just like Facebook itself, running apps on the Platform requires the Platform to keep a list of all the applications running on it. In the Open Platform, this is held in a MySQL database. Helpfully, they provide you with enough data to get you started, you just have to load it into MySQL.- Connect to MySQL using your favourite client - I'll use phpMyAdmin
- Create a user which which we'll give to the Platform so it can access the database
- In the SQL Tab, copy and paste the contents of the file
/fbopen_data_dump where fb-open-platform is the archive you downloaded and unzipped from Facebook - Run the Query
Now we have to configure the Platform to talk to the database.
- On your web server, edit a file in the fb open platform lib directory - in our example, I mean this file:
/var/www/fblib/lib/core/init.php - Change
$DB_USERNAMEto match the user you created. In my case it was 'fbopenplatform' - Change
$DB_IPto match IP address of your database server. In most cases, this will just be 'localhost' - Change
$DB_PASSWORDto match the user's password you created earlier. I'm not going to tell you what mine was ;-) - Save the file.
Hold up. You with me?
Before we go any further, lets test that the basics of the facebook open platform are up and running. In a browser, go to your http://www.example.com/fbop/fbopentest/ folder. You should see a nice list of test file we can use. At present, the most interesting one is http://www.example.com/fbop/fbopentest/fbml.php. You'll see that it loads, and you can see all the code if you view source, but its not parsing it into HTML from FBML. That's because we haven't installed the FBML parsing libraries yet!This is a little more tricky for the novice as we're not messing about with PHP anymore - but proper unix and C++ stuff, but lets have a go. I would however, ensure you have a backup of your server or virtual machine. If this screws up, it has the capacity to ruin your install of a number of other things as Sean B discovered.
Installing the FBML Parser
Back soon to finish this off.
How to Quit Twitteriffic
Twitterific rocks. Its simple, cool, and once you have Growl installed, its not as annoying. Still, sometimes it goes wrong and you need to quit it. This isn't obviously apparent as applications which sit in the menubar don't show up in the Force Quit menu (which you get by pressing Apple+Alt+Esc).
Normally you can quit Twitterific using the Quit Twitterific command in the 'spanner' or 'wrench' menu - i.e. Settings.
But, when Twitterific crashes, or any other app for that matter, you need the Activity Monitor. For those of us who are new to Mac OS X and come from Windows, thats the same as the Task Manager you can get by pressing Ctrl+Alt+Delete. In a Mac, its a standalone app. Search for it in Spotlight: "Activity Monitor".
There, you can find all the services running, including Twitterific, and close it there.
More on Grids
The more I read about this subject, the more interesting it becomes. Try this presentation by Khol Vlnh at SXSW Interactive last year. Well, that's why we use grids.
Then try Mark Boulton's post about Blueprint. Not sure I agree with all of this tho (as per my previous post).
And then theres this.... http://webpatterns.org/. Its not there yet, but looks very cool.
Wrestling with CSS Frameworks
Say you're working on a project where you need to standardise your entire layout to a grid system, and you want your entire organisation to conform to this in a single way in code? Not easy. Everyone does their layout differently, but it looks the same! Why do this, why not code the same way to make things look the same. The best way, the right way.
Granted this doesn't work for decor, typography etc, but for layout it does. This is where some CSS Frameworks come it. The main ones being YUI Grids and Blueprint CSS.
On the face of it, they looks great - especially Yahoo's Grids Builder interface. Build a page in 8 clicks, copy paste the code. Done. How easy was that!
BUT. The world is never so rosy. What about semantics? Even back in 2006, Elliot Swan talked about how un-semantic the markup is when produced using these frameworks. The principle objection is that you have to have these ugly class names like "span-6 append-3 last" all over your beautiful document structure which relate not to the type of content, but purely to the layout. Not Cool.
Or is it? Here comes pragmatism v.s. purity again. In an ideal world, what we need in CSS is class-based inheritance. So you can define a class like "menu", give it some decor code, and then tell it to inherit another class like 'span-6' which makes it fit your grid. How cool would that be. You could program your CSS just like an app. You'd never have to repeat yourself in CSS declarations, your markup could be clean, single-class-per-element, and semantic.
However, the world isn't like that. The only way to get an element to work like this it to give multiple classnames to an element -- OR -- manually build your site's css to match the grid based on your semantic classnames - meaning that just like we do now, we have to re-define the grid every time.
I'm not decided on this yet, but I'm leaning towards the pragmatism of ugly grid-based classnames ALONGSIDE nice semantic classnames too. Something like this... class="5cols menu" where '5cols' is your grid CSS, and 'menu' is obviously your semantic one.
Why do I think that? Well, layout is already implied by the position of the content in the DOM - or it should be in 90% of cases. This means that layout CSS, specifically grid and only grid layout CSS is already implied in the DOM, so why do you have to be semantic with it? Other CSS stuff like microlayouts (borders, padding), decor and typography CSS for example DO belong under semantic classname definitions.
Its a delecate balance between purity, and a pragmatic 'lets get things done' attitude. For the latter, CSS Grid frameworks make a lot of sense. However, when used carefully, they can live alongside pure semantic markup.
At least this is the best we can do until css inheritance comes along -- which'll be never.
Want another opinion? Have a read of Nate Koechley.
CakePHP Tree Behaviour
Its often really useful to be able to represent data in a tree, or self-referential way - like product categories, music genres, organisational structures etc. Often, that takes quite a bit of code. However thanks to CakePHP, we can do it in far less lines of code, thanks to a behavior var $actsAs = array('Tree');.
First create a db table as normal with an id and title. Then add three special fields: 'parent_id', 'lft' and 'rght' - all Integers. Cake uses these to manage the hierarchical relationships between each row, and it does this all behind the scenes. Next, add the behaviour tag to your model. My example is for Genres. and its as easy as this... in genre.php...
var $actsAs = array('Tree');
Some of the clever stuff happens in the Controller to make nice URL's so lets look at that now.
What I want is a URL structure like this www.example.com/genres/genre1/genre2/genre3 etc where genre 3 is the child of genre 2 which is the child of genre 1 etc. To get this behaviour, we first add a line to our app/config/routes.php file.
Router::connect('/genres/*', array('controller' => 'genres', 'action' => 'index'));
Its a very simple line which routes any sub URL to the index action of the genre controller. Then we can do all the goodness there. So, in our genres controller, we need to get to work building a clever index action.
First, we get the current URL, split it into an array on every slash using explode. If there are no other URL paths, we assume we're at the route and list all top level genres accordingly. If there are other paths, then we can lookup current genre (the last element in the array) from the database.
function index(){
$url = $this->params['url']['url'];
$genreUrl = explode('/',$url);
if (count($genreUrl)>1){
$genreCurrent = $genreUrl[count($genreUrl)-1];
if($genre = $this->Genre->findByTitle($genreCurrent)){
pr($genre);
}else{
$this->Session->setFlash('There such genre as ' . $genreCurrent);
$this->redirect(array('action' => 'index'));
}
}else{
$genres = $this->Genre->findAll("parent_id IS NULL");
pr($genres);
}
}
There are some problems with this so far. It only works if all your genre names are unique, and worse, allows you to specify any path (like www.example.com/genres/blah/this/is/wrong/validGenreName) where validGenreName is valid at any level, but the path to it does not reflect it's true higherachy. To fix this, we're now going to parse every genre given in the URL, and check to see if the one before it, and the one after it in the DB match those in the URL. This way we can ensure the URL is a true reflection of the database structure.
I've got to go now, but I'll come back and finish this post when I get another chance.
There's more info on Tree Behaviour in the CakePHP 1.2 manual.
Text to Speech
Now this is incredible.
http://www.cereproc.com/demo.html
And this... https://www.cepstral.com/demos/
Text to speech has come on a long way from the Stephen Hawking-esq stuff of the 80's.
Wanna have a real play? Make George W Bush say some dodgy stuff in this demo.