Sunday, September 27, 2009

PHP MySQLi bind_result Empty LONGTEXT

The problem is that when using the PHP MySQLi extension with prepared statements, I was getting an empty value in one of my bound variables after using $mysqli->execute(), $stmt->bind_param(), and $stmt->fetch(). If I executed the exact same query using $mysqli->query() and subsequently using $result->fetch_object() I would get the values I was looking for.

I went as far as copying and pasting the variable names associated with the column from every place they were used in the script and comparing them to make sure there were no typos.

Now, if I leave everything exactly how it is, I can toggle this behavior by switching the data type of the problematic column between TEXT and LONGTEXT. When the column is LONGTEXT then the prepared statement returns an empty string to the bound variable. If the column is TEXT then everything works as expected.

Strange behavior to say the least. I've caught a few unresolved PHP bug reports that appear to be related to this when looking for PHP MySQLi LONGTEXT, but nothing too detailed.

In any event, we'll be able to work with a TEXT column instead of using a LONGTEXT column in this application. You should probably research the impart if could have on you before switching though. Some of the older bug reports appear to mention Wordpress users struggling with this when reading from the Wordpress database for plugins.

Wednesday, September 16, 2009

Wordpress xargs: xgettext: No such file

I was getting the following error when trying to use the Wordpress i18n-tools to generate POT files for a Wordpress plugin.

xargs: xgettext: No such file or directory
Couldn't generate POT file!


At first it didn't make sense. I couldn't figure out why it wasn't finding my plugin directory or file. It hadn't donned on me that the file which couldn't be found was actually xgettext.
I'd assumed I already had gettext installed. I know it's installed on at least one of the machines around here.

In any event, took less than 5 minutes to fix by installing gettext.

sudo apt-get install gettext

Wednesday, September 2, 2009

PHP Get Oldest File

I was looking around to make sure there wasn't some sort of built-in function in PHP now for determining the oldest file in a directory. I didn't find a built-in function that returns the oldest file, but I found plenty of user functions that were not what I was looking for.

So, I wrote my own old file getter function. The function will accept either an array of file paths or a string which will be passed to glob in order to get an array of file paths. The function returns the oldest file found.

function oldest_file($dir)
{
if(is_string($dir))
{
$dir = glob($dir);
}
$oldest = array_shift($dir);
foreach($dir as $file)
{
if(filemtime($file) < filemtime($oldest))
{
$oldest = $file;
}
}
return $oldest;
}

Tuesday, September 1, 2009

PHP GD Heatmap Generation

I recently set out to write my own tools to generate a heatmap from clicks on my websites. So far the collection of click positions has been a little tricky because of things like the visitors screen being a different size than mine, javascript being enabled but Adsense being blocked which shifts the position of some elements, and a whole host of other annoyances that don't come to mind at the moment.

One thing that did come sort of easy was figuring out how to generate a heatmap image using the PHP GD image functions and x/y pairs from clicks. At first I was wondering how to get the three color areas without having later clicks overlap other clicks and throw off the flow of the colors.

Rather than working with a click at a time, I needed to generate the heatmap image one color and one click at a time. I would need to loop through the image three times, each time drawing progressively smaller circles using different colors.

I put together a simple function to draw a heatmap onto an image using a list of x/y points and an image created using GD.

<?php

function draw_heatmap($image, &$clicks)
{
if(function_exists('imageantialias'))
{// Only available with compiled in version of GD
imageantialias($image, true);
}

// Heatmap colors
$cold = imagecolorallocate($image, 0, 0, 255);
$warm = imagecolorallocate($image, 0, 255, 0);
$hot = imagecolorallocate($image, 255, 0, 0);

// Loop through the clicks and draw the largest/coldest circles first
foreach($clicks as $click)
{
imagefilledellipse($image, $click['x'], $click['y'], 30, 30, $cold);
}

// Next draw middle/warm circles over the cold ones
foreach($clicks as $click)
{
imagefilledellipse($image, $click['x'], $click['y'], 20, 20, $warm);
}

// Finally draw the smallest/hot circles over everything
foreach($clicks as $click)
{
imagefilledellipse($image, $click['x'], $click['y'], 10, 10, $hot);
}

return true;
}

$width = 200;
$height = 200;
$image = imagecreatetruecolor($width, $height);
$clicks = array(
array('x' => 123, 'y' => 123),
array('x' => 45, 'y' => 113)
);
draw_heatmap($image, $clicks);
header('Content-Type: image/png');
imagepng($image);

?>