Here’s a quick question for the wider PHP programming community … if you’re writing code that tests for the presence of an array, should is_array() also accept objects that behave like arrays?

[code lang=”php”]
$testObject = new ArrayObject(array(‘Tom’));
$testResult = is_array($testObject);
[/code]

On PHP 5.3.2, $testResult gets set to false. If you wanted to get an object that behaves like an array past this sort of test, you’d have to write:

[code lang=”php”]
$testObject = new ArrayObject(array(‘Tom’));
$testResult = (is_array($testObject) || $testObject instanceof ArrayAccess);
[/code]

I’m just curious as to what other PHP programmers think of this. Having to write the second test is longer, and there seems to be little or no benefit gained by having to do so.

What do you think?

Be the first to leave a comment »

We’re Hiring

Posted by Stuart Herbert on July 19th, 2010 in PHP In Business.

I’m looking for a PHP developer to fill a permanent web team lead developer & team leader role, based in Bath in the UK. The role is with Gradwell, a multi-award winning provider of business internet services (we’re also one of the top 50 fastest growing UK tech companies according to Deloitte), reporting directly to me in the Engineering department. We have some exciting projects (including a public-facing API) to deliver and the usual challenges of morphing legacy code to solve.

If you’re interested, drop me a line at the office (stuart.herbert at gradwell dot com) to get more details and explain why you’d be worth an interview 🙂

No agencies, thanks.

Be the first to leave a comment »

There’s a programming style I rarely see in the PHP world, but one which I use from my C programming days – programming by contract. It’s a very useful technique for writing code that is demonstrably robust, and a useful compliment to unit testing with PHPUnit.

At it’s most basic, programming by contract can be summed up as:

  • Does my function or method have inputs that are acceptable to me?
  • Has my function or method generated return data that I’m happy to pass back.

PHP has the assert() method to help with this, but it is deficient and best avoided. I’d like to share the approach I’m currently using for this, to get constructive feedback on how to evolve the style further.

At the heart of this approach lies the constraint. It is a test that must be satisfied; a bit like a runtime unit test. We could do this inline:

[code lang=”php”]
function breakMe($inputData = “I am bad data”)
{
// enforce our constraint
if (!is_array($inputData))
{
throw new Exception(‘Bad data $inputData; expected array()’);
}
}
[/code]

… but the problem with that is that it quickly bulks out your code with a lot of repetitive (and avoidable) content. An ideal candidate to make into a function or a method, which could yield:

[code lang=”php”]
function constraint_mustBeArray(&$testData)
{
if (!is_array($testData))
{
throw new Exception(“Constraint failed”);
}
}

function breakMe($inputData = “I am bad data”)
{
// our constraint is now in a nice function
constraint_mustBeArray($inputData);
}
[/code]

Here, we are trading performance (the cost of a function call) for both developer efficiency and reduced future maintenance costs. In general, the trade-off is worth it; most PHP developers work on small sites where developers are more expensive than runtime costs (within reason). The time saved from proving that code is working (and bailing immediately we prove otherwise) is worth saving.

We’re also introducing an important principle: there’s no return value to check. If execution continues on the line below the call to constraint_mustBeArray(), we can assume that the constraint was passed. If the constraint failed, we let whatever exception handlers there are, well, handle it.

There’s a couple of problems with this style that have been nagging me. It has a lot of advantages, and is probably good enough, but …

  • There’s no autoload support in PHP for functions, making it a pain to work with a large number of functions in an app or framework. Life is easier if the constraints are defined as object methods instead.
  • There’s limited potential to re-use constraints once they have been defined. They have to be explicitly called. It would be great if they could be passed into (say) a data model layer of some kind as parameters, to assist in data integrity checking. (Note the common thread of making sure that bad data is detected as early as possible, and pro-actively rejected by the app).

This led me to a more OO style:

[code lang=”php”]
class MyFramework_Array
{
static public function mustBeArray(&$testData)
{
if (!is_array($testData))
{
throw new Exception(‘Constraint failed’);
}
}
}

function breakMe($inputData = “I am bad data”)
{
// constraint is now in a reusable object method
MyFramework_Array::mustBeArray($inputData);
}
[/code]

Well, it is object-oriented for sure, but it still isn’t reusable … but it could be with lambda functions …

[code lang=”php”]
class MyFramework_Array
{
static public function mustBeArray(&$testData)
{
// create the lambda function
$constraint = function($testData)
{
if (!is_array($testData))
{
throw new Exception(‘Constraint failed’);
}
};

if ($testData !== null)
{
$constraint($testData);
}
else
{
return $constraint;
}
}
}

function breakMe($inputData = “I am bad data”)
{
// we can still call the constraint as before …
MyFramework_Array::mustBeArray($inputData);

// … but we can now also do the following …
$constraint = MyFramework_Array::mustBeArray();
$constraint($inputData);
}
[/code]

This approach gives us the flexibility of both worlds … a constraint method that we can call directly, and also a constraint function that we can assign to a variable to re-use as appropriate.

There’s still a couple of weaknesses with this approach, the most obvious one to me that finding these constraint methods is no longer quite as easy (you need to know which class they are defined on), but the counter-argument is that this is why frameworks have to rely on convention.

We’re quite heavily constrained by PHP’s syntax and parser limitations here, specifically the lack of macros (which could avoid runtime costs in production environments) and that we can’t assign lambda functions to class properties at declaration time.

I’m wondering how this style of declaring constraints could be refined further. You can take it as given that we would normally throw something other than Exception. Comments welcome 🙂

Be the first to leave a comment »

This Month

July 2010
M T W T F S S
« Feb   Aug »
 1234
567891011
12131415161718
19202122232425
262728293031