Well, working with php is colourful at the best of times, but today i encountered a bug so big, so fundamental to the design of the language, that my face almost fell off in disbelief. In short, if you're calling a method statically in PHP 4, within the static method, the '$this' keyword will point to the calling object, as opposed to being 'null' (there should be no object context in a static method). Here's an example:


class Static
{ 
  function method()
  { 
    echo get_class($this);
  }
}

class Container
{ 
  function Container()
  { 
    Static::method();
  }
}

$Container = new Container();

The output is "Container". This example is lifted off the bug report page, in which a member of the php team declares, "This is how it is implemented, no bug." . The php object model documentation backs this up,
The $this pseudo-variable is not usually defined if the method in which it is hosted is called statically. This is not, however, a strict rule: $this is defined if a method is called statically from within another object. In this case, the value of $this is that of the calling object.
What are these guys on? There can be no rational reason for this, the only explanation i can offer up is that this is a side-effect of a deficient object model implementation in PHP 4, passed off as a "feature". Moreover, it means you can't assert that the static method is actually being called statically (remember, there's not even a 'static' keyword in php 4), like so: assert("!isset($this)"); This will fail since '$this' points to the caller object! Depressing. Fundamental.

Extension Object Pattern implementation for php - uses call overloading (on which i mistakenly called bs a while back) and the reflection API:

I use a variation on this to implement Façade-like objects that present one unified interface to clients whilst delegating requests to appropriate helper objects (extensions) as they come in. You can register new extensions and all the rest. Add context awareness to the extensions (pass a reference to the parent) and you've got a clean implementation of mixins.

In reality it's an Extension Object implementation as opposed to a Façade, because façades need provide a high-level interface to a low-level subsystem, whereas this does nothing of the sort.

Façades are used all over the place, including sessions and web services. Extensions are a way of getting round the fact that PHP doesn't implement either multiple inheritance or mixins. They are also dynamic, so you can shape the capabilities of an object to fit its context.

For those of you using PHP's Flexy (Pear HTML_Template_Flexy) templating engine, this patch provides better subtemplating support. Adds a new 'partial' tag to the flexy:xxx namespace and allows for variable mapping. The word 'partial' is borrowed from the ERB templating engine (ruby). You can define variables in the subtemplate context as attributes of the new tag. This feature is pretty important for modularising templates. Usage example:


<flexy:partial src="subtemplate.html" varNameInSubtemplateScope1="#String Literal#" 
varNameInSubtemplateScope2="currentPage.var" varNameInSubtemplateScope3="var" />

My changes were made in PHP 5.0.4 on Flexy v1.2.1.

Add the function linked here to Compiler/Flexy/Flexy.php to get the 'partial' tag working. I'll see if the project integrates this feature in the future.

Much talk about RoR and will it go mainstream and blah.

I was recently asked by someone managing a RoR project why it was moving so slowly. When i inquired as to the skill-sets of the programmers involved the manager replied, "they used to be our dreamweaver guys".

OK, i thought, looking worried.

I suggested the quality of the programmers may be a factor. He looked at me puzzled, offended even. THESE GUYS ARE PERFECTLY FINE. THEY ARE WEB PROFESSIONALS. He said this with his eyes. Not with his mouth.

Matter of factly, i said, "You may need better programmers. Ruby is a powerful language."

It was like breaking bad news to a sick child. I felt really bad afterwards.

Right now i program in PHP5 with Zend 5 and the IDE, coupled with the vast array of third party libraries, cancels out the productivity boosts of Ruby the language (which is more powerful than php) and Rails the framework (which is more powerful than our homegrown php framework).

Third party libraries play an important role in all this. GEM is under-populated right now. Though gems seem to be consistently of a higher quality than a lot of the things you'll find on PEAR or CPAN, there's just not enough out there.

Will RoR become mainstream?

All i can say is:

Talent does not scale well.

A good ruby developer has demonstrably better OOP skills than a good php developer. The php developer may be better, you just have no way of knowing, because he hasn't access to as many OOP features. To run a successful RoR project you have to hire high quality ruby programmers, there's no middle ground. IMO a lot of web programmers will not migrate productively to python/ruby. Their heads will hurt and they won't program to the strengths of the language and their design will be off and it'll be PAIN PAIN PAIN for other developers on their team.

More here and here and here.

Coming onto you like the bastard brother of Assertion Roulette, i propose Assertion Monolith - when many assertions are bundled into one. For example, a load of sample data structures, followed by a method call and then something like this:


$this->assertIdentical($bigFatDataStruct, $bigFatExpectedOutputDataStruct);

Assertion Monolith is a sure sign that the test followed the implementation. Coding this way round is like showering with your clothes on, emerging with dripping garments, hanging them out to dry and spending the rest of the day walking around town naked.

No really, it is.

A monolithic assertion can contain many sub-assertions within it, but none are explicitly referred to or documented. Go through 10-20 of these assertions, and suddenly you've got a whole load of unmaintainable tests. When one monolith assertion breaks, you'll have to manually break it down into it's component assertions. Most importantly though, a monolith assertion tells you next to nothing about the code it's testing. This is an important role for tests.

So, what i'm saying is, if you're gonna go the testing route, do it incrementally, as is the TDD way.

The Test Smells section at the XUnitPatterns site is pretty great. No doubt Mr. Beck would approve.

Spent an hour hunting down a PHP bug relating to the number above. I should have noticed that this is the largest 32-bit signed integer (2^31 - 1).

So it's also the largest number PHP's integer type can handle, as you'll find if you run this PHP integer precision test (via Elliot Back):


$max = 0;
$i = 1;
$step = 1;
while($max + 1 === (int) ($max + 1))
{
    if($i === (int) $i)
    {
        $max = max($i, $max);
        $step += $step;
    } else 
    {
        $i = $max;
        $step = 1;
    }
    $i = $i + $step;
}

PHP's lack of native double precision number representation is bemusing. Floats can be used instead, though they carry representation repercussions if you want to persist them.

The native arbitrary precision math functions are available, but the morale of the story remains cautionary: don't use PHP for number crunching.

Seagull

When i rolled into work last week and sat down at my new desk, i reached in the drawer and pulled out a stack of business cards with the name 'Demian Turner' on them. Turns out Demian had recently left to pursue the development of his open source PHP framework, Seagull, full time. Seagull is the most solid PHP framework i've looked at, though i do think the competition stinks. With PHP 5 it's time for PHP developers to get their act together and roll out quality deployment, testing and development tools. Hopefully i'll be a part of that process in the coming months.

Wow. I had plans to post a lot of things on here, but for now, general busyness has overloaded all these into bullet points in an OPML file somewhere. Speaking of which, OmniOutliner is the most critical productivity application ever made, by virtue of it's complete open-endedness and masterful key binding intuition. It's a work of art.

So what's changed round here? My dissertation on social software and the World Live Web is done & dusted (more in subsequent posts), my love affair with Ruby has blossomed (more - so much more - in later posts), i'm now working as an application developer in PHP5 and my ears are filled with podcasts (Open Source & PHP related), courtesy of itunes 5, making my commute to work almost bearable.

Elsewhere the gang of four, kernighan, knuth and hofstadter are illuminating the corners of my days.

PHP5 is going to be the focus of much of my time in the coming year, this much seems certain. Ruby on Rails will take years to reach PHP's level of ubiquity with web hosts, who still seem in the process of upgrading to this new version of the language.

PHP5 features a complete rewrite of the object model. It's OOP support is so broad it seems more pertinent to point out what common OO features it doesn't implement, as opposed to which it does:

  • No C++ style templates
  • No metaclasses
  • No namespaces
  • No operator overloading

Other than this PHP5 seems to have the works. Plus a lot of MySQL/XML features i haven't gotten around to yet.

Adam Trachtenberg is the man to spill about PHP5, here's an overview of the language's new features, and here's his blog, which should be a mandatory RSS feed for any PHP developer. I also had a chat with Ed Lecky-Thompson last week, who's contributed to the Professional PHP5 title. Looks solid too, though i haven't read it yet.

Hopefully this'll all help move PHP developers away from the procedural and into strict OOP for the bigger projects, where frameworks can be built, design patterns effected, and many hours browsing tangled procedural code & rough testing methods avoided. That said, it's important to retain the rapid development capabilities that procedural PHP encourages - this sets it apart from languages like Java, after all.

And if there's one thing PHP does not want to be, it's Java.