Autoload PhpThumb with Zend Framework

Here’s an easy way to autoload PhpThumb (an excellent & fast image resizing / manipulating PHP library) using Zend Framework without having to modify the PhpThumb source at all. First we need to make our own custom autoloader:

class M_Loader_Autoloader_PhpThumb implements Zend_Loader_Autoloader_Interface {

   static protected $php_thumb_classes = array(
      'PhpThumb'        => '',
      'ThumbBase'       => '',
      'PhpThumbFactory' => '',
      'GdThumb'         => '',
      'GdReflectionLib' => 'thumb_plugins/',

   * Autoload a class
   * @param   string $class
   * @return  mixed
   *          False [if unable to load $class]
   *          get_class($class) [if $class is successfully loaded]
   public function autoload($class) {
      $file = APPLICATION_PATH . '/../library/PhpThumb/' . self::$php_thumb_classes[$class];
      if (is_file($file)) {
         return $class;
      return false;

Then simply put this in your Bootstrap:

Zend_Loader_Autoloader::getInstance()->pushAutoloader(new M_Loader_Autoloader_PhpThumb());

Done. Now you can use PhpThumb in your controllers like this:

class PhotoController extends Zend_Controller_Action {
   public function indexAction() {
      $thumb = PhpThumbFactory::create("/path/to/image.jpg");
      $thumb->adaptiveResize(250, 250);

Script to generate command to push MySQL database changes between enviornments

Got sick of manually doing database dumps between our production, test, and development environments, so I just wrote a very handy script using Zend Framework to generate a command to push changes between environments as you make them.

You will have to tweak ssh_to to suit your needs (our test and production dbs are not separated at the moment, so that removes a layer of complexity for us), but if you have everything setup in application.ini like most people do, this should work almost out of box. You’ll need to setup the autoloader on your own.

usage: php push_db.php --to=dev --from=prod


#!/usr/bin/env php5
require_once(getcwd() . '/autoload.php');

$opts = new Zend_Console_Getopt(
      'from=s'    => 'From environment, with required string parameter',
      'to=s'        => 'To environment, with required string parameter',

$from = $opts->getOption('from');
$to = $opts->getOption('to');

foreach (array('from','to') as $env) {
      if (!in_array($$env, array('production','prod','testing','test','development','dev'))) {
         die('Error: invalid parameter ' . $env . " = '{$$env}'" . PHP_EOL);

$prod_env = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'production');
$test_env = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'testing');
$dev_env = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'development');

$to_server = array();
$from_server = array();
foreach (array('from','to') as $serv) {
   $server = $serv . '_server';
   switch ($$serv) {
      case 'production':
      case 'prod':
         ${$server}['host'] =                   $prod_env->database->params->host;
         ${$server}['username'] =                   $prod_env->database->params->username;
         ${$server}['password'] =                   $prod_env->database->params->password;
         ${$server}['dbname'] =                   $prod_env->database->params->dbname;
         ${$server}['ssh_to'] = 'me@foobar';
      case 'testing':
      case 'test':
         ${$server}['host'] = $test_env->database->params->host;
         ${$server}['username'] =                   $test_env->database->params->username;
         ${$server}['password'] =                   $test_env->database->params->password;
         ${$server}['dbname'] =                   $test_env->database->params->dbname;
      case 'development':
      case 'dev':
         ${$server}['host'] = $dev_env->database->params->host;
         ${$server}['username'] =                   $dev_env->database->params->username;
         ${$server}['password'] =                   $dev_env->database->params->password;
         ${$server}['dbname'] =                   $dev_env->database->params->dbname;

print "Run this command on " . $from . ':' . PHP_EOL;
echo 'mysqldump -u ' . $from_server['username'] . ' -p' . $from_server['password'] . ' ' . $from_server['dbname']
. ' | ssh ' . $from_server['ssh_to'] . ' "mysql -u ' . $to_server['username'] . ' -p' . $to_server['password'] . ' ' . $to_server['dbname'] . '"' . PHP_EOL;


As small after-work project inspired by FitFinder (which, unfortunately, has since been taken down per the demands of the UCL), several months ago Montmere Limited launched spotadoink, the 21st century catalyst to flirting.

It was hastily thrown together in just a few short hours, but the concept is fun: when you see someone who is attractive, tell the world where!

Unfortunately it has not seen much use since its launch, but as with anything else, who knows what the future holds.

Facebook Developer Subscriptions – Part 1

So Facebook has an API.  It’s pretty full featured although the documentation seems to be a little on the weak side.

After a little glancing, I thought “I can do this” and followed the sample php code to create a “Login” page for my test site.  I then spent all kinds of time and notebook paper coming up with an elaborate series of cron jobs to use the Access Token to make requests on the user’s behalf so I can periodically check for updates while they’re away.

Then I read the manual.

Facebook offers a subscription service via Real-Time Updates where you can request to be notified of certain changes as they happen.  Facebook doesn’t actually tell you what the changes are, but they notify you that a certain type of change has occurred (new friends, activities, etc.) Cool.

Great.  So all I need to do is get a user authenticated to my application using some example code from the php SDK, let Facebook know what kinds of updates I’m interested in, and set up an endpoint to get that data.  Easy enough, right? Ha.

So the way the Facebook API works is that you request a user’s data using their Access Token (that the developer gets when the user allows a certain application access).  The main problem with using this vanilla approach with subscriptions is that the access token given when using the example code in the php SDK expires after a little while.  Well, I want to get user updates all the time so I need a token that doesn’t expire.  This requires using Extended Permissions.  A quick look through the list tells me I need the “offline_access” permission.

Unfortunately, this is where I realized that the example code in the php SDK starts to lack.  The login URL built into the SDK $facebook->getLoginURL() doesn’t allow you add your requested permission in.  We’ll need to take a few extra steps to get what we’re looking for.

First, we need to construct our own login URL. The format will look something like this:{your application ID}&redirect_URL={where to send the user after they do OR don’t authenticate}&scope=offline_access

Using this in place of the function call will cause the user to see something like this when they click on “Login”:

Request for Permissions

When your user clicks “Allow”, they will be redirected back to your redirect_url with an additional parameter called “code”.  Our neverending access token! Well, almost.  Now we need to make another request, server side time, to Facebook to turn this code into an actual access token.  This is done by requesting from a URL like this:{your application ID}&redirect_URL={where to send the user after they do OR don’t authenticate}&client_secret={your secret code made when setting up developer account}&code={the code you just got in your return URL from Facebook}

Getting this URL returns the following data:


So you’re application will have to parse our your actual access token from the string, but that should be a good start.

Update: after playing with this for a little bit, I found that the facebook session will return the access_token with extended permissions to you when your user is redirected back to your page.  This means you can do something like access $facebook->session->[‘access_token’] and save that instead of having to use curl for that second URL.

Next up: setting up your subscriptions and endpoint.

The ANTI JOIN – all values from table1 where not in table2

One of the less intuitive concepts I come across regularly in SQL is that of the ANTI JOIN. That is, requesting data from a table where some value is not in another table.

The wrong way of doing it is this:

FROM table1 t1

This is very slow and inefficient, because the RDBMS has to compare each row with an entire table of values. The following is much much faster, as it matches up each row once, then simply eliminates the results that are not in the second table:

FROM table1 t1
LEFT JOIN table2 t2 ON =

This is what is known as an ANTI JOIN.. And I really wish it were part of standard SQL.. Be careful, though,if has any NULL rows, you will experience unexpected results. Here’s my proposal, and the following should throw a fatal error if is not a NOT NULL column:

FROM table1 t1
ANTI JOIN table2 t2 ON =

Too bad I don’t make the rules.

Get the average value from the nearest date in MS SQL

Needed to get the average exchange rate for the nearest invoice to a given date, and I found a quick and easy way to accomplish this in SQL Server:

   AVG(i.exchrate) / 100 AS exchrate
   , MIN(DATEDIFF(DAY, '" . $date . "', i.invoicedate)) AS accuracy
FROM InvoiceTable i
   i.currencycode = '" . $currency_code . "'
   AND DATEDIFF(DAY, '" . $date . "', i.invoicedate) &gt; 0
ORDER BY MIN(DATEDIFF(DAY, '" . $date . "', i.invoicedate))

GROUP_CONCAT and truncation / field serialization in MySQL

I wish there were a true serialize() grouping method in MySQL, as I frequently deal with data that must be viewed as groups of tables or groups of groups of tables, and sometimes even deeper. One hacky way I occasionally use (only when there is really no other alternative, because this sucks) to accomplish this without having to resort to recursion is

GROUP_CONCAT(items, '|||')

Most datasets I work with are sane enough to safely assume I won’t find 3x consecutive pipe characters in a given field. So, I simply explode that field out into an array.

$data = array();
while ($row = $result-&gt;fetch()) {
   $row['items'] = explode('|||', $row['items']);
   // or, to eliminate null columns / empty string values:
   //$row['items'] = preg_split('/\|\|\|/', $row['items'], -1, PREG_SPLIT_NO_EMPTY);
   $data[] = $row;

One of the problems you will run into, though, as your datasets start to get a little larger, is that this is an insufficient solution since GROUP_CONCAT() truncates each row by default (on most systems) by 1024 characters. Not to worry — there is a very simple fix to this.. simply increase the value of group_concat_max_len.

DB::mysql()-&gt;exec("SET SESSION group_concat_max_len = " . PHP_INT_MAX);

Maybe someday there will be a more elegant solution to what should be an unusual problem, as it seems I come up with a nasty solution like this on a weekly basis these days.

Next on the list should be a MODE() aggregate function. Like, for real.. tell me that’s harder to implement than STDDEV_POP().

Transfering MySQL databases between Servers via SSH

Usually, when transfering a MySQL database from one server to another, people pipe the output of mysqldump into a file, archive it if it is large, upload it to the remote host, unarchive it, and then pipe it into the MySQL instance from that shell.

There is a much easier way, although it doesn’t archive the data first.. but usually unless you’re dealing with larger tables, the ease of using this method makes slower transfers very acceptable.

mysqldump -u user -ppassword databasename | ssh "mysql -u user -ppassword databasename"