"So just after some thoughts on this really... good or bad?"
Bad, really bad, I'm afraid. You're trying to make the language do something it doesn't want to do, or even: can't do. You're gluing feathers to a fish's fins, and throwing it up into the air, so it can mimic a bird's behaviour.
Your test code shows a dramatic decrease of speed (after switching to
strstr, still ~5 times slower than usual). And you're only testing your code with valid input. Besides, have you even checked if you can get this function to return what it needs to return, and to Where?
The simple fact of the matter is this: each function call with your improvised (hacked) type-hints will issue an error, even if the type is correct.
It will, however, issue a notice in these cases, too:
function test(integer $foo)
How will you recover from this error? Are you going to add:
if (settype($argument, $expected) == $argument)
to your error handler? and how are you going to deal with functions that take arrays of ints, or what if the user passes
There's just too many things to consider here.
Your approach also poses problems when you scale things up a little: Have you thought about what would happen if you used this code in tandem with a framework, that uses namespaces, sets all sorts of handlers all over the place, and uses complicated autoloading trickery?
Even simple autoloading would mean that PHP sets out to look for this
integer class. That means calling the autoloader, when that turns out to be unsuccessfull, PHP will of course use the include paths, and a lot of I/O disk access is the result. Disk I/O is a speed killer, as we all know.
Note that lookups of files that aren't found are not cached!, so each type-hint will result in disk access. Whomever is hosting this code, if it ever got used in even a medium traffic site, will not be happy.
Perhaps this has changed with PHP5.5, but most hosting services are yet to upgrade.
Each function call, in your simple example, is already approx. 5 times slower than a normal one. Add the overhead of a custom autoloader, several layers of error/exception handlers to that, and you'll see the avg time per function call drop even more (probably converging on the initial times you had). Simply because autoloaders often access the disk, too, with
file_exists calls, using the include path to scan for files who's name resembles that of the class that needs to be loaded, only to fail, and have PHP do the same disk operations again.
Then, like the example I listed: getting ints from a db, or user input means that these numbers are all passed around as strings, but are perfectly castable/usable as integers.
Suppose you were able to get the called function, cast the arguments accordingly and call the function again, what would happen? Well, the function gets called again, so another error is triggered, and your handler, which is now the caller of the function will be called twice.
Of course, the second time, owing your intervention, the types will match this time, but that's 4 function calls (5 including
call_user_func_array) + 2 errors being raised to complete a single call:
Original caller /->fails, PHP====\\
\\ //``!AUTOLOADER!``<=\\ ||
\\ || \\ \/
\=======> function -------> error \==>DISK I/O !!TWICE!! per call
\| /\ \\
?? || \==> handler, type checking + casts
|| || || /\
|| ||call_user_func_array|| |
?? |======================| |
|| \\ error2 |
|| suppose it returns, still disk I/O and
|| good luck getting back there //
An that's just assuming no intern gets the brilliant brain-wave to actually create a
integer class or interface!
Even if you manage to get all of this working, a recoverable error isn't guaranteed to have anything to do with your special-case type-hints. Your handler was created with a specific type of error in mind, which -logic dictates- should be an
Of course, you can't force the language to emit such an error when a non-custom error is encountered.
Ah well, you could try to work on this a bit more, if you want to, but I'd say you're better of spending that time to refactoring your functions like so:
* my test func - EXPECTS INTEGER
* Any decent IDE uses these doc-blocks
* @param int $integer
* @return int
$int = (int) $int;//cast to be sure
That'd be a better way to spend your time, and just ensure people you work with have a decent IDE, that parses the doc-blocks.