Привет. Неожиданно для себя столкнулся с проблемой, решил посоветоваться, как лучше решить. Я с помощью spl_autoload_register() зарегистрировал статический метод класса как автолоадер, все отлично работает, но есть одно но... Если функция не находит нужный файл - я получаю фатал, мол не найден указанный класс. Мне нужно что бы в этом случае бросалось исключение, это в идеале. Но, думаю, подойдет любой вариант, который позволит системе обрабатывать полученную ошибку, а не просто вылетать с фаталом. Как пишут на php.net в версиях пыха до 5.3 ислючения в автолоад функциях, скажем так, игнорируються, в 5.3.0+ все работает нормально. Конечно, понимаю, что это еще один повод проапдейтится, но я пока работаю с 5.2.11 Заранее благодарен за советы.
ну так если разработчики как так скажем говорят что так скажем игнорируются исключения, то какие вопросы тогда?
Имееться ввиду что невозможно в самом автолоадере бросить исключение и потом его закетчить. Но я просто не верю в то, что нету способов обработки ошибок автолоада=) trigger_error() тоже не сработал...
PHP: <?php function autoload_scan_dirs($dirs_str, &$list) { $dirs = explode(':', $dirs_str); foreach($dirs as $dir) { $elements = scandir(ROOT_PATH.$dir) or trigger_error('Error. Function: autoload_scan_dirs(). Directory "'.ROOT_PATH.$dir.'" not found.'); unset($elements[0], $elements[1]); foreach($elements as $element) if(is_dir(ROOT_PATH.$path = $dir.'/'.$element)) autoload_scan_dirs($path, $list); else $list[][ROOT_PATH.$dir] = $element; } } function autoload($name) { static $list = false; if(!$list) autoload_scan_dirs(CLASSES_DIRS, $list); $found = false; foreach($list as $class) { if($path = array_search($file = 'class.'.$name.'.php', $class)) { require $path.'/'.$file; $found = true; } } if(!$found) trigger_error('Error. Function: autoload(). Class "'.$name.'" not found.'); } spl_autoload_register('autoload'); Всё легко перехватывается.
PHP: if($path = array_search($file = 'class.'.$name.'.php', $class)) >>> PHP: if(false !== $path = array_search($file = 'class.'.$name.'.php', $class))
Hight Да, trigger_error() таки работает. Хоть я и получаю свою ошибку и сразу после нее тот же фатал... Все-таки, может существуют решения с использованием исключений?
Krasilich Да какие проблемы. Бери мой автолоад и прикручивай себе. Измени в нём, что тебе надо и всё. Вместо trigger_error выводи красивое сообщение об ошибке, а потом делай die()
вот что сделал... в контексте php 5.3 PHP: function __autoload($classname) { //creating $path @include_once $path; if (class_exists($classname)) { return true; } eval("class $classname { function __construct() { throw new Exception('Class $classname not found'); } static function __callstatic(\$m, \$args) { throw new Exception('Class $classname not found'); } }"); }
А зачем этот eval? Просто определить класс исключения (один раз) MyFukenException и написать throw new MyFukenException('Class $classname not found'); не позволяет религия или уровень интеллекта?
Кузяво - уважаю Фатальные ошибки можно еще хватать в register_shutdown_function при помощи http://php.net/error_get_last
phpbidlo Я тебе денег дам, если у тебя получиться так сделать=)) Обрати внимание на контекст в котором все происходит.
Simpliest Да тут вопрос скорее не в фатале, а в том что бы бросить исключение в автолоадере... У самого это решение вызывает чувство дискомфорта, да и не решает проблему для php <5.3, но а что делать?=))
Код (Text): <?php class MyFuckenException extends Exception { //... } function __autoload($class){ $path = $class.".php"; include_once($path); if(!class_exists($class)) throw new MyFuckenException("$class - not exist!"); } try{ $test = new ExistedClass(); $test1 = new NotExistedClass(); } catch(MyFuckenException $e){ print "Error: ".$e->getMessage(); die(); }
Вместо автолоада делаем Service Locator, в нем проверяем существование запрашиваемого класса, если нет - пробуем подключить файл, если после этого класс не появился - бросаем исключение.
phpbidlo Топик внимательно читали? В php < 5.3+ это не работает. http://simpliest.co.cc/sample/autoload/ ... eption.php
[vs] Идея, конечно здравая, но что будет если мы Service Locator'oм будем получать класс, который экстендиться от чего то??? Тут без автолоада никуда...
Из всего контекста php 5.3 там лишь __callstatic и деньги вам предлагали не за решение в рамках php 5.3+ так что не надо нам ля-ля.
Уже вам чтоли? Речь была о замене eval на непостредственный вызов throw, php 5.3 тогда вот не знаю зачем было указано. Если нужно нормальное рабочее решение - Zend_Loader тока так. Можете даже им деньги переслать.
К слову сказать, решение phpbidlo в моем случае даже при использовании php 5.3 не сработает, так как я не использую напрямую __autoload() (привел лишь для примера, каюсь что мог сбить с толку, хоть вначале я и описал в точности что использую я). Хоть, я сам, если честно, не понял в чем разница, но факт, прямой throw у меня не сработал на версии 5.3.0 в функции которая зарегистрированна spl_autoload_register().