Skip to content

Instantly share code, notes, and snippets.

@hejrobin
Created November 1, 2011 12:53
Show Gist options
  • Save hejrobin/1330448 to your computer and use it in GitHub Desktop.
Save hejrobin/1330448 to your computer and use it in GitHub Desktop.
<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);
define('TYPEHINT_PCRE', '/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/i');
class TypeHint {
private static $error_handler;
private static $type_callbacks = array(
'boolean' => 'is_bool',
'integer' => 'is_int',
'double' => 'is_float',
'numeric' => 'is_numeric',
'string' => 'is_string',
'object' => 'is_object'
);
private function __construct() {}
public static function activate() {
self::$error_handler = set_error_handler('TypeHint::handleTypehinting');
}
public static function deactivate() {
set_error_handler(self::$error_handler);
}
private static function getArgument($contexts, $fn, $index, &$argument) {
foreach($contexts as $context) {
if(isset($context['function']) && $context['function'] == $fn) {
$argument = $context['args'][$index - 1];
return true;
}
}
return false;
}
public static function handleTypehinting($error_code, $error_message, $file, $line) {
if($error_code == E_RECOVERABLE_ERROR) {
if(preg_match(TYPEHINT_PCRE, $error_message, $matches)) {
list($match, $index, $class, $fn, $hint, $type) = $matches;
if(isset(self::$type_callbacks[strtolower($hint)])) {
$argument = null;
$contexts = debug_backtrace();
if(self::getArgument($contexts, $fn, $index, $argument)) {
if(call_user_func(self::$type_callbacks[strtolower($hint)], $argument))
return true;
}
}
}
}
return false;
}
}
TypeHint::activate();
function testInteger(Integer $obj) {
var_dump($obj);
}
testInteger(15);
testInteger(1.5); // Throws catchable fatal error
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment