For some years we are able to use “array” and class names as type hints http://php.net/manual/en/language.oop5.typehinting.php and since the @internals discussion if we get type hints for literals (int, bool, …) and if so in what form is going on some time http://wiki.php.net/rfc/typecheckingweak and http://wiki.php.net/rfc/typecheckingstrictandweak i was really intrigued by a comment point out how you can do it in php 5.2+ TODAY.

function typehint($level, $message) {
    if($level == E_RECOVERABLE_ERROR && preg_match(
		'/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/', $message, $match)
	) { 
		if($match[4] == $match[5]) {
			return true;
		}
	} 
	return false;
}
set_error_handler("typehint");

If you name a “class” in a function definition that isn’t know at compile time PHP doesn’t complain. Only if you pass in the wrong value it throws an “Catchable fatal error”:

Catchable fatal error: Argument 1 passed to CLASS::FUNCTION() must be an instance of MYCLASS, WHAT_YOU_PUT_IN given.

If you now pass in a string in that function it reports it as “string given”. Combine that with the regex from above and you get:

Catchable fatal error: Argument 1 passed to CLASS::FUNCTION() must be an instance of string, string given.

The error might sound stupid but PHP expects a instance of class “string” not a literal string so that’s ok.

If you catch all these errors you have now literal type hints in your application!

GREAT?

Well let’s look at the downsides… (apart from “OMG THAT’S A FUCKING STUPID IDEA!”)

It’s slow.. really slow. I didn’t test it on a real project but for calling a million functions with one and three params the results look like this:

PHP 5.2.6, one param

5 Times slower

PHP 5.2.6, three params

12 Times slower

PHP 5.3.1 one param

30 Times slower

PHP 5.3.1 three params

45 Times slower


I haven’t really looked into WHY it’s slower on 5.3 nor tried 5.3.2 or 5.3.99 but i don’t think that really matters. Test script attached if you want to try it yourself

So for a production environment this method is somewhat unusable (given you just could patch your php if you really want that and don’t care about the trouble and not ‘reusable’ code you will get).

So what else could you do with it… well if you have a good API Documentation you could build a script to put those type hints into your code before you run your test suite… but that also did work before (putting the type checks in the first lines of the method).

I guess it’s good for nothing but showing off another way to hack around in PHP. Presumably it’s not even forward compatible to the point where PHP will have literal type hints since i guess they will call them “int/bool” and not “integer/boolean”.


Published

30 March 2010

Tags


blog comments powered by Disqus