Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обработчик для проверки типов аргументов функций 
:(
    Опции темы
ShamanVoodoo
Дата 26.1.2013, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 17.10.2007
Где: Сергиев Посад

Репутация: нет
Всего: -3



Пользовательские функции не проверяют типы принимаемых аргументов,  для того чтобы это обойти я использую обработчик. Проблема в том, что в случае ошибки проверки возникает ошибка E_ERROR и ниже идуший не выполняется, приходится оборачивать каждую фунцию проверяющую типы аргументов в try catch , а мне хотелось бы чтобы выводилась ошибка E_NOTICE и код продолжал свое выполнение.

Посоветуйте что делать? Использовать set_exception_handler('exception_handler')? 
Может у кого-то есть в наработки в данном направлении? 
Буду благодарен за любую помощь!

Код

// Обработчик типов аргументов функций

final class TypeHint
{
    
    static private $TypeHints = array(
        'boolean'    => 'is_bool',
        'bool'        => 'is_bool',
        'integer'    => 'self::is_int',
        'int'        => 'self::is_int',
        'float'        => 'self::is_float',
        'double'    => 'self::is_float',
        'string'    => 'is_string',
        'resource'    => 'is_resource',
        'strict'    => 'self::is_strict',        // Имена классов\функций\аргуметов
        'url_param'    => 'self::is_url_param',    // параметр ЧПУ ссылки
        'file_name'    => 'self::is_file_name',    // Имя файла
    );
    
    // Проверка на соотвествие типу integer \ int
    static private function is_int( $value )
    {
        if( ( is_numeric($value) && is_string($value) && preg_match( '/^[-]{0,1}[0-9]+$/u', $value ) ) || is_int($value) )
        {
            return TRUE;
        }
        else 
        {
            return FALSE;
        };
    }
    
    // Проверка на соотвествие типу float \ double
    static private function is_float( $value )
    {
        if( ( is_numeric($value) && is_string($value) && preg_match( '/^[-]{0,1}[0-9]+\.[0-9]+$/u', $value ) ) || is_float($value) )
        {
            return TRUE;
        }
        else 
        {
            return FALSE;
        };
    }
    
    // Проверка на соотвествие типу strict
    static private function is_strict( $value )
    {
        if( is_string($value) && preg_match( '/^[a-z_\x7f-\xff]{2,}[a-z0-9_\x7f-\xff]*$/iu', $value ) )
        {
            return TRUE;
        }
        else 
        {
            return FALSE;
        };
    }
    
    // Проверка на соотвествие типу url_param
    static private function is_url_param( $value )
    {
        if( ( is_string($value) || is_int($value) ) && preg_match( '/^[a-z0-9_\x7f-\xff]+$/iu', $value ) )
        {
            return TRUE;
        }
        else 
        {
            return FALSE;
        };
    }
    
    // Проверка на соотвествие типу file_name
    static private function is_file_name( $value )
    {
        if( is_string($value) && preg_match( '/^[a-z0-9_\x7f-\xff]+\.[a-z0-9_\x7f-\xff]+$/iu', $value ) )
        {
            return TRUE;
        }
        else 
        {
            return FALSE;
        };
    }
    
    // Создание объекта возможно только через метод initializeHandler
    private function __construct() {}
    
    // Инициализация обработчика
    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']) && $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;
                        }
                        else
                        {
                            throw new ErrorException( $ErrMessage, 0, $ErrLevel, $ErrFile, $ErrLine );
                        };
                    };
                };
            };
        };
        
        return FALSE;
    }
    
}

// Инициализируем обработчик
TypeHint::initializeHandler();

// Тест
function test( strict $arg1, file_name $arg2, $arg3 = 1 ) { echo "<br>{$arg1} | {$arg2} | {$arg3}"; };

try{ test( 'func_2', array(1,2) ); } catch( ErrorException $e ) { echo "<br>".$e->getMessage(); };
try{ test( 10.1, 'str' ); } catch( ErrorException $e ) { echo "<br>".$e->getMessage(); };
try{ test( 'class_name', '02.jpg' ); } catch( ErrorException $e ) { echo "<br>".$e->getMessage(); };

PM MAIL ICQ   Вверх
Arantir
Дата 26.1.2013, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: нет
Всего: 55



Замените 
Код

throw new ErrorException( $ErrMessage, 0, $ErrLevel, $ErrFile, $ErrLine );
 на 
Код

trigger_error($ErrMessage."; Level: ".$ErrLevel."; File: ".$ErrFile."; Line: ".$ErrLine);
trigger_error по умолчанию возвращает ошибку уровня E_USER_NOTICE, т.е. код будет обрабатываться дальше.

php все же язык без строгой типизации, так что, в отличии от языков со строгой типизацией, неправильный тип аргумента тут не является несовместимым с жизнью и в принципе можно выдавать только Notice.

Это сообщение отредактировал(а) Arantir - 26.1.2013, 16:50


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
ShamanVoodoo
Дата 26.1.2013, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 17.10.2007
Где: Сергиев Посад

Репутация: нет
Всего: -3



Arantir > не работает

Выдает
Notice: Argument 1 passed to test() must be an instance of strict, double given, called in ...\www\index.php on line 94 and defined; Level: 4096; File: ...\www\index.php; Line: 92 in ...\www\core\class.TypeHint.php on line 132
Catchable fatal error: Argument 1 passed to test() must be an instance of strict, double given, called in ...\www\index.php on line 94 and defined in ...\www\index.php on line 92

и дальше не выполняется

Смысл данного решения в выборочной проверке аргументов, которую до этого приходилось проверять в самом коде функции.  Сама же проверка требуется чтобы не выполнять код функции впустую, создавая при этом доп. нагрузку. Кто
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Extensions | Следующая тема »


 




[ Время генерации скрипта: 0.1262 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.