March 9th, 2010 — Design Patterns, PHP
Giorgio Sironi of Invisible to the Eye wrote this great post about the Observer Design Pattern. It explains the whole concept really well but personally I’m a fan of the “Event Dispatcher” implementation of the concept (ala Symfony Components) so I thought I’d take a moment to explain it.
In the standard implementation we register an observer with the observed object and it is responsible for calling the listeners that are observing it. In the event dispatcher implementation we tell a separate object to listen out for events and what to do when they happen. Then objects which are observed “fire” the event with the dispatcher.
The code listing I’ve included leaves a lot to be desired but I didn’t want to over complicate the explanation with details like caching the configuration, passing multiple parameters or allowing the Fire method to ignore event return values. All highly desirable features of a good Event Dispatcher but overkill for this explanation.
<?php
class EventDispatcher {
private $events;
public function __construct() {
$this->events = array();
}
public function Listen( $event_name, $event ) {
if ( ! array_key_exists( $event_name, $this->events ) ) {
$this->events[ $event_name ] = array();
}
$this->events[ $event_name ][] = $event;
}
public function Fire( $event_name, $data ) {
// if there are no events registered just return the data
if ( ! array_key_exists( $event_name, $this->events ) ) {
return $data;
}
// call each event handler in the order they were registered
foreach ( $this->events[ $event_name ] as $event ) {
$data = call_user_func( $event, $data );
}
// return whatever the events have done to the data
return $data;
}
}
function shorten( $data ) {
return substr( $data, 0, 8 );
}
$ed = new EventDispatcher();
$ed->Listen( 'foo', 'strtoupper' );
$ed->Listen( 'foo', 'shorten' );
$ed->Listen( 'bar', 'shorten' );
$foo = $ed->Fire( 'foo', 'hello world' );
$bar = $ed->Fire( 'bar', 'hello world' );
echo "Foo = $foo\n";
echo "Bar = $bar\n";
?>
Why is this good?
- We don’t need to implement an interface for the observers, we just provide a PHP callable.
- We don’t even need an object if it’s not necessary but we can provide one when it is.
- We don’t need to write notification code for everything that can be observed, the event dispatcher takes care of that.
Why the original?
The original implementation has its origins in strongly typed languages such as Java where you can’t just do $foo = $bar and worry about the implications later. This means you need the interface to allow the polymorphism necessary to have an array of arbitrary listeners. What’s more, you can’t just create functions and pass them around as callable strings. They have to exist within an object. These language features make the original pattern the “right” way to do it but when you can pass strings around and call them later, why wouldn’t you?
March 8th, 2010 — MySQL
Today’s lesson learned. MySQL 4 won’t let you use bound parameters in the LIMIT clause.
SELECT foo, bar, baz FROM some_table WHERE foo = ? LIMIT ?, ?
That’s fine in MySQL 5 but in v4 it’ll complain about a syntax error near ?, ?
March 7th, 2010 — PHP
Well that’s an hour of my life I’d like back please …
My afternooon has been spent trying to integrate my code with a third party script and third party database structure. After a hefty amount of time spent debugging it turns out I’m storing date/time values as timestamps and trying to bind/insert them into the database that way.
When you use a MySQLi bound parameter with a datetime column you have two choices. Enclose the parameter marker with a MySQL call to FROM_UNIXTIME or insert it with parameter type ’s’ and use MySQL’s datetime string format ‘Y-m-d H:i:s’.
Here’s some example code shamelessly stolen from a StackOverflow post -
$stmt = $mysqli->prepare('insert into foo (dt) values (?)');
$dt = '2009-04-30 10:09:00';
$stmt->bind_param('s', $dt);
$stmt->execute();
March 6th, 2010 — PHP
After a morning of playing about with iContact’s API I’ve cobbled together a PHP wrapper class to handle the basics of what I want to do. So far that only extends to adding contacts and then subscribing them to an existing list but I’ve written a couple of helper functions that should make implementing the rest fairly trivial.
You can download the source along with a couple of quick demo scripts here.
And now for a quick “do this, do that” getting started guide that’ll hopefully save you a couple of hours of head banging.
Sign Up (and pay for) a real account
Despite their claims that the free trial gives you access to everything, it turns out you have to have a paid for account in order to sign up for the sandbox. Go figure.
But at $9.95 a month to get started it’s hardly going to break the bank.
Sign Up for you sandbox account - http://sandbox.icontact.com/
On this first screen you need to enter your regular username/password. If you have a trial (unpaid) account it’ll say it’s an invalid username.
Assuming your account is in good standing you’ll then be able to sign up for an account on the sandbox.
Register your application – Here
Once you’ve given the application a name and description you’ll be given an application ID.
Enable access to your sandbox account
In the same area you need to enable access to your account for that application ID. This requires that you create yet another password (with good reason!) so let’s do a quick recap of the credentials you have -
- Username and password for your regular iContact account.
- Username and password for your sandbox iContact account.
- App ID and password for your API application.
In order to use your application you will need to provide your sandbox username, the application id and the password that enables access to the account. Please note that’s not the password you use to login to the sandbox!
Request your account id and client folder id
Before you can make use of the API in any useful way you need to request your account id and client folder id (which then need to be included in the URL of all subsequent requests). The demo script shows this off way better than I can explain in words but in a nutshell you need to issue a GET on https://app.sandbox.icontact.com/icp/a/ to get the account id followed by a GET on https://app.sandbox.icontact.com/icp/a/{$accountid}/c/ to get the client folder id.
After that all requests should be made to https://app.sandbox.icontact.com/icp/a/{$accountid}/c/{$clientfolderid}
The wrapper script I’ve written handles all of this for you. Enjoy.
Gotchas
To round this off here’s a quick list of the random “gotchas” that I either encountered myself or read about during my playing with this API in the hopes that you won’t fall for the same ones.
If you use PHP CURL to connect to the API and try to use the example code provided by iContact it’ll fail on some hosts because it’s missing a couple of lines which they’re nice enough to include in a post in the forum but not nice enough to update into their example code.
curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $handle, CURLOPT_FAILONERROR, false );
Make sure to properly error check the response you get. PHP’s json_decode is a very smart function but if, like me, you get errors/warnings from the iContact server instead of a valid response your code may fail in interesting ways. Most notably don’t just assume the response is valid json and look up indexes that might not be there. isSet and array_key_exists are your friend.
March 5th, 2010 — Witter
It’s 10pm on a Friday night. I’ve passed up two separate pub invitations and an evening with the girlfriend in order to keep working on Viral Link Directory. Tonight’s mission, email marketing integration.
I’ve been a long time Aweber user, thanks mostly to my signing up three years ago when they were still crazy cheap. But their lack of integration features and over zealous application of the double opt-in system make them really hard to integrate into other applications.
Enter iContact …
They make some bold claims on their website. The most important of which being, “iContact v2 API is designed to expose nearly all of iContact capabilities to help you build new and innovative email marketing applications. It is designed from the ground up to be easy to use, flexible, and powerful.”
Yes, that’s right, everything exposed via a web2.0 style API!
It was a rocky start. Their supposed 15 day “all features” free trial doesn’t actually include access to the developer sandbox and it took the best part of a day to discover that was why I couldn’t get my account details to work. Then I discover they don’t accept PayPal (I like to run all my business finances through PayPal to ease the job at the end of the tax year) and to round it all off they manage to get my card suspended for suspected fraud … thanks guys!
But after an hour spent alternating between talking to their customer support people (who don’t actually seem to be able to do anything other than talk to people who can do things) and talking to my bank (who have recently been bought out and replaced all their phone systems with ones even their own staff don’t seem to understand) I finally paid the $8.67 to get access.
So the support is terrible, the API documentation even worse (seriously guys, why do you have a discussion forum but not a 1 page “do this, do that” getting started tutorial?!?) but wow is their API cool.
So far I’ve only tested a few of the functions but it does appear I have absolutely full control over my account. Creating mailing lists, subscribing contacts to them, sending messages … everything. And most importantly, they give me the choice of whether I want to use confirmation emails or not. Now don’t get me wrong. I have no intention of using this to spam people who don’t want to hear from me but it does mean I can handle the full double opt-in system myself in my own application and treat iContact as a second class citizen that just does what I tell it.
I’ll have a full integrating PHP class to post up shortly along with hopefully finding time to write the “do this, do that” getting started tutorial I wish I’d been given earlier today.
Who needs the pub when you can geek out and then blog about it?
March 5th, 2010 — HTML/CSS
Somehow I’ve managed to make the same mistake twice while developing Viral Link Directory. First on the main interface a few days ago and then again on the admin interface today.
Both use freely available templates that I “acquired” from the last developer to work on this project. Both have HTML that is “nearly there” and both have a pretty naff style sheet. Unfortunately, I approached fixing them both up in the same way.
With a stylesheet that looked like it just needed a bit of tuning I scanned the HTML to get the gist of it and started changing attributes to achieve the effects I wanted. But when your stylesheet is sitting on top of bad HTML that just never works out. Everything behaves that little bit more oddly, particularly across multiple browsers.
The key take away from this is that it didn’t just make me feel better in a Zen kind of way to get the HTML right, it actually made the job easier and faster.
Well formed HTML then great CSS …
March 4th, 2010 — PHP
What better way to start a blog …
<?php echo 'Hello World'; ?>