Данный пост посвящается любителям typehint'ов и строгой типизации, которой у PHP нет по определению.
копаясь недавно в мануалах по PHP, набрел на раздел о typehint'инге, и совершенно случайно полез в комментарии, где и нашел великолепное (хотя и тяжелое) решение для PHP5, как сделать язык строго типизированным. Под катом решение.
define('TYPEHINT_PCRE' ,'/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/');
class Typehint {
private static $Typehints = array(
'boolean' => 'is_bool',
'integer' => 'is_int',
'float' => 'is_float',
'string' => 'is_string',
'resrouce' => 'is_resource'
);
private function __constrct() {}
public static function initializeHandler() {
set_error_handler( 'Typehint::handleTypehint' );
return TRUE;
}
private static function getTypehintedArgument( $ThBackTrace, $ThFunction, $ThArgIndex, &$ThArgValue ) {
foreach ( $ThBackTrace as $ThTrace ) {
// Match the function; Note we could do more defensive error checking.
if ( isset($ThTrace[ 'function' ] ) && $ThTrace[ 'function' ] == $ThFunction) {
$ThArgValue = $ThTrace[ 'args' ][ $ThArgIndex - 1 ];
return TRUE;
}
}
return FALSE;
}
public static function handleTypehint( $ErrLevel, $ErrMessage ) {
if ( $ErrLevel == E_RECOVERABLE_ERROR ) {
if ( preg_match ( TYPEHINT_PCRE, $ErrMessage, $ErrMatches ) ) {
list ( $ErrMatch, $ThArgIndex, $ThClass, $ThFunction, $ThHint, $ThType ) = $ErrMatches;
if ( isset ( self::$Typehints [$ThHint] ) ) {
$ThBacktrace = debug_backtrace();
$ThArgValue = NULL;
if ( self::getTypehintedArgument ( $ThBacktrace, $ThFunction, $ThArgIndex, $ThArgValue ) ) {
if ( call_user_func( self::$Typehints[ $ThHint ], $ThArgValue ) ) {
return TRUE;
}
}
}
throw new Exception( $ErrMessage );
}
}
return FALSE;
}
}
Typehint::initializeHandler();
И вот несколько тестов:
function teststring(string $string) { echo $string; }
function testinteger(integer $integer) { echo $integer; }
function testfloat(float $float) { echo $float; }
try {
teststring( 'string2' );
testinteger( 14 );
testfloat( 14.0 );
} catch ( Exception $e ) {
echo $e->getMessage();
}
оригинал