Zend Developer ZoneZend Framework 1.10.7 Released (30.7.2010, 17:52 UTC)
The Zend Framework team announces the immediate availability of Zend Framework 1.10.7, our seventh maintenance release in the 1.10 series. This release includes around 60 bug fixes. For those uses of Zend_Service_Twitter , please ensure you upgrade to 1.10.6 or 1.10.7 ASAP. These releases introduce a change in the Zend_Service_TWitter API that enforces the use of OAuth by default when using methods that require authentication. The change was introduced to help prepare Zend Framework users for the Twitter OAuthcalypse in mid-August. (If you cannot upgrade, there are other ways to integrate Zend_Oauth with Zend_Service_Twitter .)
Link
Chris ShiflettAuto Increment with MongoDB (29.7.2010, 19:52 UTC)

We are currently working on an app that uses a number of technologies, including PHP, Python, and MongoDB. Recently, a need arose to use sequential identifiers for users, similar to an auto_increment column in MySQL.

If you've used MongoDB, you might be familiar with the default behavior of using a UUID as the primary key. This is convenient, especially if you partition your database across servers, because you don't have to coordinate the primary key in any way. If you use sequential identifiers (as I demonstrate in this post), you can use multiple servers and interleave identifiers by advancing each server's sequence by the total number of servers. (For example, with two servers, advance each sequence by two, so one server generates even identifiers, and the other generates odd.)

I'd rather not discuss the advantages and disadvantages of either approach, because it's exactly this debate that makes it very difficult to find any useful information on using sequential identifiers with MongoDB. Instead, I'm just going to explain how I did it, and hope this is helpful to someone. :-)

First, create a sequence collection that you can use to determine the next identifier in the sequence. The following creates a collection called seq that has a single sequence in it (for users), but you can add as many as you need:

db.seq.insert({"_id":"users", "seq":new NumberLong(1)});

If you assign seq to 1 instead of new NumberLong(1), it will be interpreted as a float due to a JavaScript quirk.

Before adding a new user, you need to increment the sequence by one and fetch the next identifier. Fortunately, the findandmodify() command provides an atomic way to do this. Using the MongoDB shell, the command would look something like this:

db.seq.findAndModify({
    query: {"_id":"users"},
    update: {$inc: {"seq":1}},
    new: true
});

Because I'm using Lithium, I added a method for fetching the next identifier to my User model:

<?php
 
namespace app\models;
 
class User extends \lithium\data\Model {
 
    static public function seq() {
        $seq = static::_connection()->connection->command(
            array('findandmodify' => 'seq',
                  'query' => array('_id' => 'users'),
                  'update' => array('$inc' => array('seq' => 1)),
                  'new' => TRUE
            )
        );
 
        return $seq

Truncated by Planet PHP, read more at the original (another 2980 bytes)

Link
Sean CoatesA Case of Mistaken Iterator (29.7.2010, 15:30 UTC)

Earlier this week, I spent most of a day tracing through code in search of the source of a bug that was causing part of our application to fail in strange ways.

In the back end, we have models that connect to CouchDB. These models implement the Iterator pattern to allow easy traversal of a record’s keys.

When I wrote the code to implement Iterator several months ago, I dutifully checked the PHP Manual and adapted the reference example that I found there:

<?php
class Record implements Iterator
{
    // (partial class, showing the iterator implementation only)

        public $_data = array();

        public function rewind()
        {
                reset($this->_data);
        }
 
        public function current()
        {
                return current($this->_data);
        }
 
        public function key()
        {
                return key($this->_data);
        }
 
        public function next()
        {
                return next($this->_data);
        }
 
        public function valid()
        {
                return (current($this->_data) !== false);
        }

}

Little did I realize that this implementation is very broken. I’ll explain why, below.

Over the past few years, I’ve implemented many iterators in this way, using PHP’s implicit array manipulation functions (reset(), current(), key(), next()). These functions are very convenient because PHP arrays are so powerful — arrays in PHP work like ordered hash tables in other languages.

PHP’s implicit management of an array’s iteration index (the value that is incremented by next() and referenced by key()) is indeed convenient, but the convenience can sometimes be offset by its very implicitness — the value is hidden from you, the PHP programmer.

In PHP, generic array iteration (without the implicit iterator) isn’t actually as simple as it sounds. Remember that arrays aren’t arrays in the traditional sense, but ordered hash tables. Consider this:

$data = array('zero','one','two','three');
for ($i=0; $i<count($data); $i++) {
    // yeah, don't calculate count() on every iteration
    echo "{$data[$i]}\n";
}

Output:

zero
one
two
three

This first example is easy to iterate — the array contains sequential, numeric, zero-based keys. It gets more complicated when using non-sequential, and non-numeric keys:

$data = array(
    'apple',
    'cow' => 'moo',
    'pig' => 'oink',
    'orange'
);
for ($i=0; $i<count($data); $i++) {
    echo "{$data[$i]}\n";
}

Output:

apple
orange
Notice: Undefined offset: 2 in - on line 10
Notice: Undefined offset: 3 in - on line 10

I could use foreach, but because a numeric loop illustrates the point more clearly, here’s how I might implement the above code so that it works:

$data = array(
    'apple',
    'cow' => 'moo',
    'pig' => 'oink',
    'orange'
);
$k = array_keys($data);
for ($i=0; $i<count($data); $i++) {
    echo "{$data[$k[$i]]}\n";
}

Output:

apple
moo
oink
orange

This brings us back to the Iterator implementation. Why isn’t the code above correct? Take a closer look at this:

public function valid()
{
    return (current($this->_data) !== false);
}

A value of false in the array is indistinguishable from a false value returned by current(). Using the above implementation with the following array would cause it to bail after orange (and subsequently might cause you to waste a day tracking down the cause):

array(
    'apple',
    'orange',
    false,
    'banana',
);

On Tuesday night, I updated the manual to use an improved Iterator implementation. It’s probably a bit slower (so you can use the internal-indexing implementation if you’re sure your arrays will never contain false), but my implementation is more robust.

<?php
/**
 * A mixed-key iterator implementation
 *
 * Note: these array_keys() calls are slow. The array keys could be cached
 * as long as the cache value is invalidated when $_data is changed.
 */
class It implements Iterator
{
        public $_data = array();
        protected $_index = 0;

        public function rewind()
        {
                $this->_index = 0;
        }
 
        public function current()
        {
                $k = array_keys($this

Truncated by Planet PHP, read more at the original (another 765 bytes)

Link
blog.phpdeveloper.org » PHPSpeaking at Dallas TechFest 2010 – Building a Web Service API (27.7.2010, 18:33 UTC)

Just a heads up for all of those in the Dallas/Ft. Worth area – there’s a great one-day event coming up this Friday (July 31st) blending PHP, .NET, Java, new media, Joomla and WordPress into one packed day of sessions – Dallas TechFest 2010 at the University of Texas at Dallas.

I’ll be giving a session called “Building a Web Service API” from 10:30 – 11:45am in the PHP track. Here’s a summary of the session:

When is a web application more than just a web application? Hook up an API and you’ll see! I’ll walk you through the basics of what an API is and the concepts behind it as well as key pieces of technology you can use to create both the client and server. There’s a focus on PHP but other languages and tools will be touched on as well.

There’s still time to register for the event – tickets can be purchased for an early bird price (ending today) of $50 or $60 at the door. You can see the full list of sessions here.

Link
Sean CoatesBeer Alchemy Integration (27.7.2010, 16:48 UTC)

As I mentioned in my previous post, my beer recipes are now online.

I've had several people ask me how this is done, so I think a post is in order.

While it's entirely possible to brew beer at home without any fancy gadgets, there are several tools I use (such as my refractometer) that make the process easier, more controlled, or both. Brewing software is one of the few instruments that I'm not sure I'd want to brew without. I use a Mac, primarily, so Beer Alchemy (BA) is the obvious choice for recipe formulation, calculation, and logging.

BA has its own HTML export mechanism for recipes, and I used this for quite a long time, but I was never really satisfied with the results. The markup was hard to style, contained a lot of clutter (occasionally useful, but often redundant information such as style parameters), and simply didn't fit well with the rest of my site.

Beer Alchemy HTML Output

You can also export from BA in PDF (not suitable for web publishing), ProMash's binary recipe format (a pain to convert, although there do seem to be some tools to help with this), BeerXML (normally the most accessible, but in my opinion, a poorly-designed XML format), or in BA's native .bar ("Beer Alchemy Recipe") format, which is what I chose.

Beer Alchemy Recipe Export Dialog

The bar format contains a property list, similar to those found throughout Apple systems. Property lists are either binary or XML (but the XML is very difficult to work with using traditional tools because of the way it employs element peering instead of a hierarchy to manage relationships). Luckily, I found a project called CFPropertyList that allows for easy plist handling in PHP. (I even contributed a minor change to this project, a while ago.)

Once you've run the .bar file's contents through CFPropertyList, layout is very simple. Here's most of the code I use to generate my recipes:

<?php
$beerPath = __DIR__ . '/../resources/beer/';

$recipes = apc_fetch('seancoates_recipes');
$fromCache = true;
if ($recipes === false) {
        $fromCache = false;
        foreach (new DirectoryIterator($beerPath) as $f) {
                if ($f->isDot()) {
                        continue;
                }
                if (substr($f->getFilename(), -4) != '.bar') {
                        continue;
                }
                $cfpl = new CFPropertyList($beerPath . '/' . $f->getFilename());
                $recipe = $cfpl->toArray();
                $title = $recipe['RecipeTitle'];
                $recipes[self::slugify($title)] = array(
                        'title' => $title,
                        'content' => $recipe,
                );
        }
        asort($recipes);
        if ($recipes) {
                apc_store('seancoates_recipes', $recipes, 3600); // 1h
        }
}

In addition to displaying the recipe's data, I also wanted to show the approximate (calculated) beer colour. Normally, beer recipes declare their colour in "SRM" (Standard Reference Method). There's no obvious, simple, and direct way to get from SRM (which is a number from 0 to 40—and higher, but above the mid 30s is basically "black") to an HTML colour.

I found a few tables online, but I wasn't terribly happy with any of them, and keeping a dictionary for lookups was big and ugly. I like the way Beer Alchemy previews its colours, and since it has HTML output, I emailed the author to see if he'd be willing to share his algorithm. Steve from Kent Place Software graciously sent me an excerpt from his Objective C code, and I translated it to PHP. This might be useful for someone, and since Steve also granted me permission to publish my version of the algorithm, here it is:

<?php
/**
 * Calculate HTML colour from SRM
 * Thanks to Steve from Kent Place Software (Beer Alchemy)
 *
 * @param float $srm the SRM value to turn into HTML
 * @return string HTML colour (without leading #)
 */
public function srm2html($srm)
{
        if ($srm <= 0.1) { // It's water
                $r = 197;
                $g = 232;
                $b = 248;
        } elseif ($srm <= 2) {
                $r = 250;
                $g = 250;
                $b = 60;
        } elseif ($srm <= 12) {
                $r = (250 - (6 * ($sr

Truncated by Planet PHP, read more at the original (another 3023 bytes)

Link
Henri BergiusAloha and the art of semantic web content (27.7.2010, 16:31 UTC)

To bring CMS editing to the next level, the IKS project is working on a semantic HTML5 editor. This week we had a hackathon in Helsinki focusing on implementing our ideas with the Aloha Editor. In addition to enjoying the hot summer weather here, we accomplished quite a bit and in the end were able to present the whole pipeline of:

  • Loading content from Midgard CMS to Aloha Editor
  • Annotating our content with Google-compatible Person RDFa elements
  • Saving the content back to Midgard
  • ...and finally analysing the content with FISE to find more semantic information

iks_helsinki_hackathon_participants.jpg

The hackathon participants included developers from Nemein, Gentics, Infigo, Salzburg Research and the German Research Center for Artificial Intelligence. Some screenshots:

aloha-editing-small.png
Editing content with Aloha in Midgard

aloha-editing-rdfa-small.png
Annotating persons with the Aloha RDFa plugin

aloha-generated-rdfa-small.png

RDFa annotation created with the semantic editor
fise-analysed-content-small.png
Additional semantic information suggested by FISE

All the relevant code can be found from GitHub (see also the FISE Midgard integration).

Link
Sebastian BergmannUsing HipHop for Static Analysis (27.7.2010, 09:30 UTC)

HipHop for PHP, the source code transformer that turns PHP code into C++ code that can then be compiled with g++, can also be used for static code analysis to find problems in PHP source code.

sb@vmware Money % hphp -t analyze --input-dir .
running hphp...
creating temporary directory /tmp/hphp_Zz7AXg ...
parsing inputs...
parsing inputs took 0'00" (20 ms) wall time
inferring types...
inferring types took 0'00" (10 ms) wall time
saving code errors, dependency graph and stats...
all files saved in /tmp/hphp_Zz7AXg ...
running hphp took 0'00" (208 ms) wall time

The script below takes a CodeErrors.js file (which is generated by hphp and in the example above is saved to /tmp/hphp_Zz7AXg) as its input and print an XML document in Checkstyle's format (the same XML format that is also used by PHP_CodeSniffer, for instance). This XML logfile can then be used with Hudson, for instance, in a continuous integration context.

<script src="http://gist.github.com/490858.js">
Link
Lorna MitchellKeynoting at PHPNW10 (27.7.2010, 06:55 UTC)
I'm slightly surprised but mostly wildly excited to announce that I'll be the keynote speaker at the PHP North West Conference in October. It is held in Manchester in the UK, which is about an hour from where I live in Leeds, so it is definitely my "home" conference, and this makes me even more excited since I know I'll be in such great company!

The talk is Teach A Man To Fish: Coaching Development Teams and really it's about how a little investment of time or effort can build your existing team into something better - and how that team can then sustain its improvements and continue to raise its performance and the game of the individual team members. All in all I am pretty excited about this talk - as with most of my conference talks, it started life as a rant in a bar, and I'm now excited to be preparing it for a more formal setting!

The event itself is a must-see for anyone doing PHP or allied technologies that can get there (Manchester is pretty central and pretty cheap - if you're in the UK, you have no excuses!). It's a Saturday event, 9th October 2010 and tickets are on sale - the Early Bird prices are still available and we've held the prices as low as possible again, we don't need frills, we just want lots of people to be able to join in! I hope to see quite a few of you there, let me know if you're coming :)
Link
Marco Tabini⇥ PHP 5.2 support ends just as its adoption begins (23.7.2010, 13:45 UTC)

In case you missed it, the PHP team has just released 5.2.14, which effectively ends active support for the 5.2 branch1:

This release marks the end of the active support for PHP 5.2. Following this release the PHP 5.2 series will receive no further active bug maintenance.

The logic behind this decision is… puzzling.

Several large projects—WordPress and Drupal among them—recently announced that they intend to push support for 5.2 into their products with their next major release. For example, Drupal 7 will accept 5.2 features, and the WP folks are just working on EOL’ing their support for PHP 4.

This means that a large number of people are just beginning learning, using and stress-testing PHP 5.2. Remember—these projects have very large user bases, so even moving a small percentage of adopters over to a different platform means a big shift. Perhaps—just perhaps—it might be better to reconsider canning 5.2. If, from a technical perspective, the move from 5.2 to 5.3 is an easy one, there is a huge psychological barrier to finally adopting 5.2 only to have it yanked from under your feet.

The real issue at hand, however, is the fact that these large user communities are not engaged in the PHP world, and vice-versa. Ignoring the hundreds of thousands of Drupal and WordPress integrators and developers is bad for both PHP and for those products; we should, instead, try our best to open a dialogue between all the communities that are centred around PHP and ensure that everyone’s interests are properly represented.

This is not to say that the fact that WP has only now decided to move to PHP 5.2 should necessarily affect the progress of PHP, nor that the PHP developers should take a “we don’t need you” attitude toward projects that are based on the language. Ultimately, it’s up to these projects if they want to actively contribute back to PHP or not, and that is the only way for them to effectively affect the development of the language itself.

However, PHP development is too unevenly connected to downstream adopters. Some—particularly framework makers—have an unusually high level of participation in deciding how PHP evolves, and that needs to change.

At least year’s WDC, a small conference organized by Microsoft, I made this very same point and managed to bring a room full of developers into complete disarray in less than five minutes—which means that, in addition to the fact that my ability to drive a bunch of people up the wall in no time flat has not changed over the years, there is plenty to talk about.

[Update: the latest 5.2.x release is 5.2.14, not 5.2.11 as I originally stated. Thanks to Ilia for pointing that out.]

  1. As I understand it, this means no more added features or bug fixed. Presumably, security issues will still be taken care of.
Link
Sebastian BergmannGTAC 2010 (23.7.2010, 13:20 UTC)

I have been invited to attend the 5th Annual Google Test Automation Conference, better known as GTAC, in Hyderabad, India in October. I am very much looking forward to discuss cutting edge challenges in test automation and evaluate potential solutions, especially with this year's focus on testability.

Another thing I like about this year's GTAC is that the participants are responsible for selecting the presentations for the conference. Here is my submission:

Challenges in Unit Testing PHP Applications

According to TIOBE, PHP is the most popular programming language after C/C++ and Java. The language has made strong inroads into large-scale, business-critical Web systems. In the six years since the release of PHP 5 -- which not only kickstarted the development of PHP-based frameworks for Web development but also the development of tools for dynamic and static testing techniques -- the PHP community as a whole has developed an increasing interest in developing software that delivers the best possible quality.

When PHP developers start to write unit tests they rarely find themselves without any constraints that are imposed by prior work of less than optimal quality. It is a well-known fact that writing unit tests for legacy code is hard. In the case of PHP it can be even harder: the legacy code has not only been written without testability in mind, but it may have been written for earlier versions of PHP that encouraged practices that make the code next to impossible to unit test.

PHPUnit, the de-facto standard framework for unit-testing PHP code, has some unique features not found in other xUnit test frameworks that allow the testing of untestable code. While developers should not use these features (as they are not required when writing tests for testable code), these features ease the pain of writing tests for legacy code and thus help developers get started with unit testing before they refactor the code for testability.

This session, presented by the creator of PHPUnit, highlights the challenges developers are facing when unit testing legacy PHP code. Some of these challenges will be familiar to developers that use other programming languages such as Java but they will see a new perspective on the problem and different approaches to solve it.

Although I am hoping, of course, that my submission will be accepted by my peers, I know that GTAC will be valuable for me even if I do not get to present: the "hallway track" of GTAC 2008 was amazing.

Link
LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP