Eсли нет 7ки, то только так:
<?php
// Обработчик типов аргументов функций
final class TypeHint
{
static private $TypeHints = array(
'boolean' => 'is_bool',
'bool' => 'is_bool',
'string' => 'is_string',
'resource' => 'is_resource',
// Подменил ряд стандартных функий, чтобы числа переданные строкой не вызывали ошибок
'integer' => 'self::is_int',
'int' => 'self::is_int',
'float' => 'self::is_float',
'double' => 'self::is_float',
// Для примера добавил несколько собственных типов:
'strict' => 'self::is_strict', // Имена классов\функций\аргуметов
'url_param' => 'self::is_url_param', // Параметры ЧПУ ссылки
'filename' => 'self::is_filename', // Има файлов
);
// Проверка на соотвествие типу integer \ int
static private function is_int($value)
{
if ((is_numeric($value) AND is_string($value) AND preg_match('/^[-]{0,1}[0-9]+$/u', $value )) OR is_int($value))
{
return TRUE;
}
return FALSE;
}
// Проверка на соотвествие типу float \ double
static private function is_float($value)
{
if ((is_numeric($value) AND is_string($value) AND preg_match('/^[-]{0,1}[0-9]+\.[0-9]+$/u', $value)) OR is_float($value))
{
return TRUE;
}
return FALSE;
}
// Проверка на соотвествие типу strict
static private function is_strict($value)
{
if (is_string($value) AND preg_match('/^[a-z_\x7f-\xff]{2,}[a-z0-9_\x7f-\xff]*$/iu', $value))
{
return TRUE;
}
return FALSE;
}
// Проверка на соотвествие типу url_param
static private function is_url_param($value)
{
if ((is_string($value) OR is_int($value)) AND preg_match('/^[a-z0-9_\x7f-\xff]+$/iu', $value))
{
return TRUE;
}
return FALSE;
}
// Проверка на соотвествие типу filename
static private function is_filename( $value )
{
if (is_string($value) AND preg_match('/^[a-z0-9_\x7f-\xff]+\.[a-z0-9_\x7f-\xff]+$/iu', $value))
{
return TRUE;
}
return FALSE;
}
// Создание объекта возможно только через метод initializeHandler
private function __construct(){}
private function __clone(){}
private function __wakeup(){}
// Инициализация обработчика
static public function initializeHandler()
{
set_error_handler('TypeHint::handleTypeHint');
return TRUE;
}
// Получение аргументов функции
static private function getTypeHintedArgument($ThBackTrace, $ThFunction, $ThArgIndex, & $ThArgValue)
{
foreach ($ThBackTrace as $ThTrace)
{
if (isset($ThTrace['function']) AND $ThTrace['function'] == $ThFunction)
{
$ThArgValue = $ThTrace['args'][$ThArgIndex-1];
return TRUE;
}
}
return FALSE;
}
// Обработчик
static public function handleTypeHint($ErrLevel, $ErrMessage, $ErrFile, $ErrLine)
{
if ($ErrLevel === E_RECOVERABLE_ERROR)
{
if (preg_match('/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/u', $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 ErrorException($ErrMessage, 0, $ErrLevel, $ErrFile, $ErrLine);
}
}
}
}
return FALSE;
}
}
// Инициализируем обработчик
TypeHint::initializeHandler();
// Тест
function test(strict $arg1, filename $arg2, $arg3 = 1)
{
echo "It's work! {$arg1} | {$arg2} | {$arg3}";
}
try
{
test('func_2', array(1,2))
}
catch (ErrorException $e)
{
var_export($e->getMessage());
}
try
{
test(10.1, 'str')
}
catch (ErrorException $e)
{
var_export($e->getMessage());
}
try
{
test('class_name', '02.jpg')
}
catch (ErrorException $e)
{
var_export($e->getMessage());
}