Category: PHP

Configuring PHP 5 with SOAP on Media Temple dv 3.5

I recently upgraded to a dv 3.5 from Media Temple for a project, but found that PHP was not configured with the SOAP extension needed for the site. With some help from the lovely Media Temple support people, here’s what I did to get it working without having to completely reinstall PHP.

Disclaimer: These instructions worked for me on a dv 3.5; it may not work for other dv packages.

Checking your current PHP installation

You can use phpinfo() to check your PHP installation and see whether or not the extension you need is already installed. If it’s not listed, it’s worth checking the PHP documentation to see how it suggests installing it. In my case, the SOAP extension is only available if PHP was configured with the –enable-soap option.

Getting SOAPy!

You will need to compile the SOAP shared module and add it to the existing PHP configuration. To do this, you’ll need to make sure you’ve installed the dv 3.5 Developer Tools. To do this, go to your Account Center, select your domain, find Root Access & Developer Tools and hit install.

Open up a terminal and SSH into your server. If you don’t know how to do this, read up on getting SSH access to your server.

  1. You’ll need to grab the latest PHP source code. Download it to somewhere convenient, like the home directory:

    cd ~

    wget http://php.net/get/php-5.2.5.tar.gz/from/us.php.net/mirror

  2. Decompress the tarball:

    tar -zxf php-5.2.5.tar.gz

  3. Move into the source directory and configure PHP with SOAP enabled (this may take a few minutes):

    cd php-5.2.5

    ./configure –enable-soap=shared

  4. Run the build (again, this may take a few minutes):

    make

    When that’s done, you can optionally test the build, which threw errors for me, but it all worked nonetheless:

    make test

  5. Copy the SOAP module into the existing PHP installation:

    cp modules/soap.so /usr/lib/php/modules/

  6. Add the SOAP module to the PHP configuration:

    echo “extension=soap.so” > /etc/php.d/soap.ini

  7. Restart Apache:

    /etc/init.d/httpd restart

  8. Tidy up by deleting the files we downloaded, e.g.:

    cd ~

    rm -rf php-5.2.5*

The SOAP module should now be loaded and ready to rock; you can check using phpinfo() again.

PHP + Twitter + Google Calendar + SMS

Working on a little side project, I wanted to be able to add an event to Google Calendar by text message like our American friends can using GVENT. I figured I could hook my Twitter account up to Google Calendar using their APIs. I tinkered with it for a couple of hours and it works!

Background

If you don’t know about Twitter, it’s a free service that allows you to share messages with your network of friends by a number of means, which includes via text messages sent to Twitter from your mobile phone.

Twitter has this useful feature called direct messages. It enables private messaging between friends over the Twitter system, provided you and your friend are following each other on Twitter. This means that you can send a message over the system without it turning up in your public time line of messages – your ‘tweets’. You just put a letter ‘D’ and your friend’s Twitter username in front of your message and send. So, I can send a text message to Jon via Twitter like this “d jontangerine Why, I’d love tangerines by post! Thank you!”

How is this useful for adding an event to Google Calendar? Well, a short text message is all I need to add an event using Google Calendar’s really smart Quick Add feature. A script set up to periodically check for new direct messages via the Twitter API can take the body of any message and pass it to the Google Calendar API.

It’s a bit round about in implementation, but it allows you to update a Google Calendar by SMS. In fact, you could use any Twitter-ing interface (Twitter.com, Twitterific), but then you may as well Quick Add your event with Quicksilver (Mac users) or some other widget or even – shock horror – sign into the Google Calendar site!

Obviously, I’m not the only person who’s thought of hooking up the APIs; Twittercal will give you basic functionality if that’s all you need. It doesn’t allow you to post to any calendar other than your default one, which wasn’t useful for my application, and I wanted to be able to do a bit of processing in PHP before posting the event to the calendar.

Twitter to PHP

So, I can set up a new Twitter account for my application, become friends with it (!) and send messages to it. That’s a good start. Now I need a PHP script that listens in for new direct messages on my new Twitter account.

To interact with Twitter, it helps to be familiar with the Twitter API. You might also find a wrapper for the Twitter API useful. It’s not entirely necessary, but will save you a bit of time. Here’s one David Billingham made earlier: Twitter PHP Library (Ver 0.1). It’s not complete, but it’s a good start.

I’ll not use the library for now so that I can show you how to talk to Twitter using our friendly PHP CURL functions.

  1. Set yourself up with an account for your application. Follow the new account and make sure it’s following you as well. Direct messages won’t work unless the feeling’s mutual!
  2. Grab the code below and save it to a new file on your Web server, e.g. “tcal.php”. The code is commented to guide you through what it does.
  3. Set TWITTER_CREDENTIALS to your application’s Twitter username and password.
  4. Make sure you have some direct messages sent to the Twitter account. Try sending it a test message, something like “d yourapp Smashing Pumpkins in The O2 Arena on Saturday at 7pm”.
  5. Run the script and you should see your messages in XML.
<?php

// Define credentials for the Twitter account define('TWITTER_CREDENTIALS', 'twitter_username:twitter_password');
// Set up CURL with the Twitter URL and some options $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://twitter.com/direct_messages.xml'); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Twitter uses HTTP authentication, so tell CURL to send our Twitter account details curl_setopt($ch, CURLOPT_USERPWD, TWITTER_CREDENTIALS);
// Execute the curl process and then close $data = curl_exec($ch); curl_close($ch);
// If nothing went wrong, we should now have some XML data echo '<pre>'.htmlentities(print_r($data, true)).'</pre>';
?>

Using a library obviously tidies things up and should provide some built-in error checking and return an XML object to us. You can use the library I mentioned earlier, but you’ll need make sure you add your Twitter account details to the class. We end up with this:

<?php

// The Twitter library require_once 'twitter.class.php';
// Create a new Twitter object and query for direct messages $twitter = new Twitter(); $direct_messages = $twitter->directMessages();
// We should now have some XML data in an object echo '<pre>'.htmlentities(print_r($direct_messages, true)).'</pre>';
?>

Okay, now we have a nice XML object to work with.

Google Calendar from PHP

Now we’re tuned into Twitter, we want to send any messages on to Google Calendar.

The Google Calendar API is a Google data (GData) API. The easiest way to interact with Google Calendar in PHP is with Zend’s standalone GData client library. This library also comes as part of the Zend Framework, but unless your application uses the framework already, it’s a bit of a sledgehammer!

The GData client library needs PHP version 5.1.4 or higher. If you want PHP 4 compatibility, this might make life a bit harder for you. PHP 4 coming to the end of its life and support for it ceased at the end of 2007. If you’re not yet using PHP 5, I strongly suggest your developments move towards using it.

After downloading the client library and installing the ‘Zend’ directory somewhere useful in your application, you can start to use it! Try adding this chunk of code in place of where we echoed the XML data from Twitter. Again, the comments tell you what’s going on.

<?php

// Define credentials for the Google Calendar account define('GCAL_USER', 'google_user@example.com'); define('GCAL_PASS', 'google_password');
// If you need to target a specific calendar, uncomment and enter // its calendar ID here. The calendar ID is available on the // calendar settings page, next to the Calendar Address buttons. //define('GCAL_ID', '[hash]@group.calendar.google.com');
// Include Zend GData client library require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata'); Zend_Loader::loadClass('Zend_Gdata_ClientLogin'); Zend_Loader::loadClass('Zend_Gdata_Calendar');
// Get Google Calendar service name (predefined service name for calendar) $service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
// Authenticate with Google Calendar $client = Zend_Gdata_ClientLogin::getHttpClient(GCAL_USER, GCAL_PASS, $service);
// Iterate through the direct messages we got from Twitter foreach ($direct_messages as $dm) { $message = (string)$dm->text;
// If you echo the message body here, you'll notice that the // extraneous text is removed from its beginning for us //echo $message;continue;
// You could do some processing here if you wanted; // e.g. allow only direct messages from certain users detect // a particular flag or message format for processing
// Create a new Google Calendar object $calendar = new Zend_Gdata_Calendar($client);
// Create a new event $event = $calendar->newEventEntry();
// Make it a Quick Add event $event->quickAdd = $calendar->newQuickAdd('true');
// Add our message as the event content $event->content = $calendar->newContent($message);
// Send the new event to be added to Google Calendar if (defined('GCAL_ID')) { $newEvent = $calendar->insertEvent($event, 'http://www.google.com/calendar/feeds/'.GCAL_ID.'/private/full'); } else { $newEvent = $calendar->insertEvent($event); }
// Play nice and ensure there's a wait between calls sleep(1); }
?>

Running that should post your direct message on to Google Calendar and, provided Google Calendar understood your message, a new event will be added.

Once we’ve used the message, we don’t want it to get picked up and processed when the script is next run. We can delete a message using the Twitter API, but we’ll need to add something to the Twitter library we’ve been using. The following function can be added to the Twitter class to allow us to delete a direct message using its ID. I put this in after the other direct message functions.

<?php	// ...

/** * Deletes a direct message */ function deleteDirectMessage($id) { if (!is_numeric($id)) { return false; } $request = 'http://twitter.com/direct_messages/destroy/'.$id.'.xml'; return $this->process($request); }
// ... ?>

Now we just call this new method of the Twitter class to delete the message once we’re done with it.

<?php	// ...

// Send the new event to be added to Google Calendar if (defined('GCAL_ID')) { $newEvent = $calendar->insertEvent($event, 'http://www.google.com/calendar/feeds/'.GCAL_ID.'/private/full'); } else { $newEvent = $calendar->insertEvent($event); }
// Delete the direct message $twitter->deleteDirectMessage((integer)$dm->id);

// Play nice and ensure there's a wait between calls sleep(1); }
?>

And we’re done! All that’s left to do it set up a cron job on a server to run our script periodically.

I advise not running the script too often – bombarding the Twitter servers. I set mine to run every 20 minutes, but from what I’ve read you should be able to run it every minute without any trouble. If you’re going to be doing anything particularly intensive, you should probably contact Twitter first.

Here’s the code in full. Enjoy!

<?php

// Define credentials for the Google Calendar account define('GCAL_USER', 'google_user@example.com'); define('GCAL_PASS', 'google_password');
// If you need to target a specific calendar, uncomment and enter // its calendar ID here. The calendar ID is available on the // calendar settings page, next to the Calendar Address buttons. //define('GCAL_ID', '[hash]@group.calendar.google.com');
// The Twitter library // Make sure you've set your Twitter username and password and // added the function deleteDirectMessage() require_once 'twitter.class.php';
// Include Zend GData client library require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata'); Zend_Loader::loadClass('Zend_Gdata_ClientLogin'); Zend_Loader::loadClass('Zend_Gdata_Calendar');
// Create a new Twitter object and query for direct messages $twitter = new Twitter(); $direct_messages = $twitter->directMessages();
// Get Google Calendar service name (predefined service name for calendar) $service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
// Authenticate with Google Calendar $client = Zend_Gdata_ClientLogin::getHttpClient(GCAL_USER, GCAL_PASS, $service);
// Iterate through the direct messages we got from Twitter foreach ($direct_messages as $dm) { $message = (string)$dm->text;
// If you echo the message body here, you'll notice that the // extraneous text is removed from its beginning for us //echo $message;continue;
// You could do some processing here if you wanted; // e.g. allow only direct messages from certain users detect // a particular flag or message format for processing
// Create a new Google Calendar object $calendar = new Zend_Gdata_Calendar($client);
// Create a new event $event = $calendar->newEventEntry();
// Make it a Quick Add event $event->quickAdd = $calendar->newQuickAdd('true');
// Add our message as the event content $event->content = $calendar->newContent($message);
// Send the new event to be added to Google Calendar if (defined('GCAL_ID')) { $newEvent = $calendar->insertEvent($event, 'http://www.google.com/calendar/feeds/'.GCAL_ID.'/private/full'); } else { $newEvent = $calendar->insertEvent($event); }
// Delete the direct message $twitter->deleteDirectMessage((integer)$dm->id);
// Play nice and ensure there's a wait between calls sleep(1); }
?>

Related

del.icio.us proxy v1

April 2, 2008: version 1.1 released.

A little while back, Ian Lloyd mentioned that he could not save links to del.icio.us because the site is blocked at his workplace. So, I wrote a proxy using PHP.

What does it do?

The proxy allows you to save bookmarks to your del.icio.us account without going to the del.icio.us site itself.

So, why is that useful? Say you’re at work and your friendly IT department have decided that de.icio.us is an evil distraction and must be blocked to save the company from going under. You still want to save bookmarks to your del.icio.us account and this is where the proxy comes in.

Once installed, the proxy sits somewhere on your own website – which is hopefully not blocked as well – and waits patiently for you to send it a bookmark. It will save the bookmark to your del.icio.us account for you using an interface kindly provided by the folks at del.icio.us (their API).

So, the proxy saves your bookmarks to your del.icio.us account by proxy, hence its name. Obviously, the del.icio.us service must be available in order to use the proxy.

Download and install

Download del.icio.us proxy

That link also takes you to the installation instructions. The proxy is fairly easy to install, even for people with little PHP knowledge. You just set a few things and upload it to an area of your site.

Once installed, it’s a cinch to use. It’s not been tested extensively in the wild yet, so consider this version a beta release. Having said that, Ian says he’s been using it for a little while with no problems, so I figured I’d finally release it for others to use.

I hope people find it helpful. Enjoy!

Notes

After some initial theatrics with throttling, writing a proxy was quite straightforward. To begin with it seemed that, despite sticking to the API rules about not querying the server too often, querying del.icio.us from my domain had been permanently blocked.

Having discussed my intent and my code with the friendly del.icio.us support team, I’m assured that this shouldn’t be a problem. However, thanks to a tweet from Shiflett, I coded in some extra protection against being throttled.

If you do get throttled by del.icio.us while using the proxy, I suggest you get in touch with del.icio.us directly to sort it out quickly.

Thanks

The proxy uses the PhpDelicious library written by the lovely Ed Eliot. Thanks Ed.

The idea to check for the del.icio.us account’s last update time before posting to it came from Chris Shiflett. Ta Chris.

The inspiration for the proxy in the first place came from Ian Lloyd. Cheers, m’dear.

Updates

April 2, 2008

Version 1.1 released with important fixes.

December 6, 2007

Version 1.0.1 released with annoyance fixes.

CakePHP 1.2: config for the console

I hope readers will forgive yet another fleeting entry from me. My Internet connection has been unusually unreliable for about six weeks and since Monday it has been disconnecting around ten times a day. Eugh.

In other news, I’ve been using CakePHP recently. So far I’m finding it pretty good. It’s all starting to come together, but the somewhat distributed documentation makes Google my best friend for development right now! I’m finding some useful little bits as I go, so I thought I’d share things as I discover them.

Setting up the new console in CakePHP 1.2

I found it easy enough to set up the console. One of the first things I did was watch some of the screencasts, including one on setting up the terminal to run console shells from the command line. No problem. But…

Problems connecting to the datasource

I hit a bit of a problem when I wanted to play with the Access Control List (ACL) component. The console couldn’t access the database when I tried to set up the database tables:

cake acl initdb

It had the correct details from the database config file, but it just wouldn’t connect. Specifically, I was getting this

Can't connect to local MySQL server through socket '/etc/mysql.sock'

Grr. The website connected to the database fine when browsing. Hmmm. MySQL seemed to be behaving. Double hmmm. I began thinking it must be a permissions issue somewhere.

Nope, it turns out that localhost hadn’t been resolving to my local IP address. Putting in the IP (127.0.0.1) as the database host fixed everything. I’m guessing that command line PHP, or at least my installation of it, doesn’t do name lookups.

Huge thanks to the lovely and wonderful lornajane for helping me track down the problem. This saved me for some additional pain on what has already been a painful week! If this little nugget helps you too, feel free to comment and say thanks to Lorna with me!