Discovery, BBC, Guardian, Discovery Again, Wikipedia, Independent

Processing Blobs

As Processing recently hit 1.0 I thought I’d take a quick look. It seems to work on the same principle as a unit test suite or a web framework – you develop “inside” the library, so it can abstract all that Java complexity away from you. Fill out setup() and draw() methods, press a button to run, press a button to export as an applet. Embedding the applet in Wordpress is actually a lot more frustrating than writing the damn thing (Solution: I resorted to an iframe. I don’t really want to waste time because Wordpress is being “smart”).

Processing is an awful lot of fun. It evokes a feeling of exploration that I haven’t had since the BBC Basic days – experimenting with maths, mapping it to a plane, just to see what it looks like.

I doubt anyone reading this via RSS will be able to see the applet, but you’re only missing lens-flare-esque coloured blobs. Click and hold to draw. Right-click to clear.

Source code: TransparentEllipses

I’ve had a search running on abebooks for well over a year for the word “anthropodermic”.

Yesterday, I finally got a hit from a book dealer in Texas. The book is from the library of Joseph Sadony, a 20th century mystic, and was presented to him by Fernand Angel.

Aurora Alegre del dichoso dia de la Gracia Maria Santissima Digna Madre de Dios, Francisco Antonio de Vereo, 1727″.

Anthropodermic bibliopegy is the practice of binding books in human skin. Yours for just US$16,895.

I’ve added Chris Dean to the list of web developers in Hampshire. I also updated the OPML summary.

I was trying to figure out the best way to test the myfputcsv() function I posted yesterday. Reading the data from disc before comparing it seemed like a step where errors could creep in, but there was no obvious way round that, as the purpose of the function is to write to disc.

Then I realised I could use PHP’s (fairly) new IO streams to dump the function’s output to a temporary buffer, and read it back in for comparison. Not perfect, but it removes concerns about file mutexes, permissions, unique filenames, etc. and speeds up the tests, as they never touch disc.

It wasn’t worth building on top of PHPUnit for this… checking failure conditions can wait for another day. I just wrote a quick script that compares the output of fputcsv() and myfputcsv(). (And it worked – I’ve already fixed two errors in yesterday’s post).

This is the first time I’ve reached for php://memory. It’s obviously useful for testing code that writes to disc, but I’m now wondering where else it might come in handy.

<?php
 
require_once 'myfputcsv.php';
 
function write( $function, $array )
{
    $fp = fopen( 'php://memory', 'w+' );
    $function( $fp, $array );
    rewind( $fp );
    return fread( $fp, 1024 );
}
 
function test( $array )
{
    $fputcsv = write( 'fputcsv', $array );
    $myfputcsv = write( 'myfputcsv', $array );
    if ( assert( '$fputcsv === $myfputcsv' ) )
    {
        echo "OK" . PHP_EOL;
    }
}
 
test( array() );
test( array( "Hello", "World" ) );
test( array( "He\nllo", "World" ) );
test( array( "He\\"llo", "World" ) );
test( array( "He llo", "World" ) );
test( array( "He\tllo", "World" ) );
test( array( "He\"\"llo", "World" ) );
test( array( "He,llo", "World" ) );

I recently needed an fputcsv() with a couple of modifications (I needed fields quoted unconditionally, and more than one character in the delimiter field). I looked at a couple of versions from the man page comments, but they were buggy in one way or another, and PHP4-specific.

The function below is as close as I can get to fputcsv()’s behaviour. I’m throwing it out there in the hope that it will be useful to someone, someday. It should be easy enough to modify to suit specific requirements.

/**
 * myfputcsv()
 *
 * Mimics the observed behaviour of PHP's fputcsv()
 *
 * Requires at least PHP 5.2.0 due to reliance on __toString
 *
 * @param resource $fp valid file pointer
 * @param array $fields array of values
 * @param string $delimiter optional parameter sets the field delimiter character. Defaults to ','
 * @param string $enclosure optional parameter sets the field enclosure character. Defaults to '"'
 * @return bool the length of the written string, or FALSE on failure
 */
function myfputcsv( $fp, $fields, $delimiter = ',', $enclosure = '"' )
{
    /**
     * Validate incoming values
     *
     * Weird corner cases are checked for here, so we can mimic fputcsv() as closely
     * as possible. Eg we check whether or not an object passed as $delimiter or
     * $enclosure implements __toString
     */
    if ( !is_resource( $fp ) )
    {
        trigger_error( __FUNCTION__ . '() expects parameter 1 to be resource, ' . gettype( $fp ) . ' given', E_USER_WARNING );
        return false;
    }
    if ( !is_array( $fields ) )
    {
        trigger_error( __FUNCTION__ . '() expects parameter 2 to be array, ' . gettype( $fields ) . ' given', E_USER_WARNING );
        return false;
    }
    if ( is_object( $delimiter ) && method_exists( $delimiter, '__toString' ) )
    {
        $delimiter = ( string ) $delimiter;
    }
    if ( is_object( $enclosure ) && method_exists( $enclosure, '__toString' ) )
    {
        $enclosure = ( string ) $enclosure;
    }
    if ( $delimiter == null )
    {
        trigger_error( __FUNCTION__ . '(): delimiter must be a character', E_USER_WARNING );
        return false;
    }
    if ( $enclosure == null )
    {
        trigger_error( __FUNCTION__ . '(): enclosure must be a character', E_USER_WARNING );
        return false;
    }
    if ( !is_scalar( $delimiter ) )
    {
        trigger_error( __FUNCTION__ . '() expects parameter 3 to be string, ' . gettype( $delimiter ) . ' given', E_USER_WARNING );
        return false;
    }
    if ( !is_scalar( $enclosure ) )
    {
        trigger_error( __FUNCTION__ . '() expects parameter 4 to be string, ' . gettype( $enclosure ) . ' given', E_USER_WARNING );
        return false;
    }
    if ( strlen( $delimiter ) > 1 )
    {
        trigger_error( __FUNCTION__ . '(): delimiter must be a single character', E_USER_NOTICE );
        $delimiter = $delimiter[0];
    }
    if ( strlen( $enclosure ) > 1 )
    {
        trigger_error( __FUNCTION__ . '(): enclosure must be a single character', E_USER_NOTICE );
        $enclosure = $enclosure[0];
    }
 
    /**
     * Prepare fields for writing to file by escaping them and wrapping them
     * in $enclosure
     */
    for( $i = 0; $i < sizeof( $fields ); $i++ )
    {
        /**
         * Make a decision on whether or not to use $enclosure
         */
        $use_enclosure = false;
        if ( strpos( $fields[$i], $delimiter ) !== false )
        {
            $use_enclosure = true;
        }
        if ( strpos( $fields[$i], $enclosure ) !== false )
        {
            $use_enclosure = true;
        }
        if ( strpos( $fields[$i], "\" ) !== false )
        {
            $use_enclosure = true;
        }
        if ( strpos( $fields[$i], "\n" ) !== false )
        {
            $use_enclosure = true;
        }
        if ( strpos( $fields[$i], "\r" ) !== false )
        {
            $use_enclosure = true;
        }
        if ( strpos( $fields[$i], "\t" ) !== false )
        {
            $use_enclosure = true;
        }
        if ( strpos( $fields[$i], " " ) !== false )
        {
            $use_enclosure = true;
        }
 
        if ( $use_enclosure == true )
        {
            $fields[$i] = explode( "\$enclosure", $fields[$i] );
            for( $j = 0; $j < sizeof( $fields[$i] ); $j++ )
            {
                $fields[$i][$j] = explode( $enclosure, $fields[$i][$j] );
                $fields[$i][$j] = implode( "{$enclosure}{$enclosure}", $fields[$i][$j] );
            }
            $fields[$i] = implode( "\$enclosure", $fields[$i] );
            $fields[$i] = "{$enclosure}{$fields[$i]}{$enclosure}";
        }
    }
 
    /**
     * Write fields as a $delimiter-delimited string, and return number of
     * bytes written
     */
    return fwrite( $fp, implode( $delimiter, $fields ) . "\n" );
}

A base class is "a class from which other classes are derived".

Many OO languages have the concept of a single base class from which all other classes are explicitly or implicitly descended. For example, Ruby, Java and .NET all have Object.

It’s a very common belief that PHP implements stdClass as a base class for all objects, but this is in fact not the case:

<?php
 
class DoesNotExtend {}
 
class DoesExtend extends stdClass {}
 
$doesNotExtend = new DoesNotExtend();
$doesExtend = new DoesExtend();
 
var_dump($doesNotExtend instanceof stdClass);
var_dump($doesExtend instanceof stdClass);

Outputs:

bool(false)
bool(true)

When I started in web development a few years ago I had to move to Birmingham and London to find work – the local web industry was pretty much DOA. I’m not sure why that was… possibly companies gravitated towards the fibre in Docklands and the financing in the city, or London’s pool of experienced workers was larger. Anyway, technology on the South Coast tended to be focused on defence contracting.

Today there are certainly more developers out there, but they’re not very visible – a Google search for “PHP Developer Portsmouth” throws up pages of job ads, rather than pages of local PHP developers. Other technology- and location-specific searches return similar results.

In an effort to change this, and to make the local development community a bit more “joined-up”, I’ve been collecting local developers’ blogs. I’m hopeful that in the long-term these blogs will form the core of a local web development community, but at the very least, if we talk to each other, if we’re active online and network around subjects of common interest, it will raise everyone’s profile. I know that Adam Wintle wants to do similar things over at Refresh Portsmouth, so anyone who’s keen on real-world meet-ups should talk to him.

If you’re at all interested in web development on the South Coast, please import this handy OPML file into your RSS reader, and check back for updates occasionally. Alternatively, the HTML list is after the break. If you want to be added to the list, or you know someone who should be on there, please just let me know.
Read the rest of this entry »

Based on the arguments summarised here, but mostly in the hopes of fostering interesting discussion, I’ve decided to turn off rel=”nofollow” on comments. The flip-side of that is that I’m going to be a lot more willing to delete comments made in bad faith.

When a language is defined by its implementation rather than a standard, it can sometimes be tricky to decide what should be considered correct behaviour and what should be considered an implementation bug.

What follows isn’t so much a PHP trick as a fix for something that really should work, but doesn’t. Although the manual implies that the behaviour described below is specific to Zend Engine 1, all my tests were performed against Zend Engine 2.2, PHP 5.2.5.

Quoting from the manual:

The Zend Engine 1, driving PHP 4, implements the static and global modifier for variables in terms of references. For example, a true global variable imported inside a function scope with the global statement actually creates a reference to the global variable. This can lead to unexpected behaviour which the following example addresses:

<?php
function test_global_ref() {
    global $obj;
    $obj = &new stdclass;
}
 
function test_global_noref() {
    global $obj;
    $obj = new stdclass;
}
 
test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
?>

Executing this example will result in the following output:

NULL
object(stdClass)(0) {}

http://uk2.php.net/static

The example above uses instances of stdClass, but attempts to assign references to scalar values, arrays or resources to global variables have the same result: the attempt to modify the global fails without error (even with error_reporting(E_ALL)), and the global retains whatever value it had before the function call.

The workaround is very simple – assign the reference via the $GLOBALS superglobal:

<?php
 
function test_global_ref()
{
    $GLOBALS['obj'] = &new stdclass;
}
 
test_global_ref();
var_dump($obj);

Outputs:

object(stdClass)#1 (0) { }

I think one of these scripts must expose an implementation bug – either assigning a reference to a global variable should work, in which case the first script should not fail, or it should not work and the second script should fail. It would be interesting to get an opinion from someone involved in language internals on how PHP should behave. In either case, it’s very hard to understand why the first script doesn’t currently cause a notice or error to be thrown when the assignment fails.

« Older entries § Newer entries »