PHP обработка ИС

HTML, CSS, DOM, XML, AJAX, (LW)AMP и т.д. CMS и веб-форумы, веб-дизайн и веб-программирование, специализированные языки и технологии.

Модератор: xdsl

PHP обработка ИС

Сообщение [DD] 28 сен 2010, 09:11

На днях разрабатывая класс для автозагрузки других классов наткнулся на следующую ситуацию.
Код: Выделить всё
<?php

class vpAutoload{
static private $registered;
static private $classes=array(
  "vpfield" => "db/vpfields.class.php",
  "vpquery" => "db/vpquery.class.php",
  "vptable" => "db/vptable.class.php",
  "vpschema" => "db/vpschema.class.php",
  "vpview" => "core/vpView.class.php",
  "vpsystem" => "core/vpSystem.class.php",
  "vpapplication" => "core/vpApplication.class.php",
);
static private $usrClass = "/usr/classes/";
static private $sysClass = "/engine/lib/";
static private $classExt = ".class.php";
static private $baseDir;

static public function register($baseDir)
{
  if(self::$registered)
  {
   return;
  }
  self::$baseDir = $baseDir;
  ini_set("unserialize_callback_func", "spl_autoload_call");
  if(false===spl_autoload_register(array('vpAutoload','autoload')))
  {
   throw new Exception("Не удалось запустить автозагрузчик.");
  }
  self::$registered = true;
}

static public function autoload($className)
{
  $class = strtolower($className);
  echo "loading class {$className}<br>";
  if(key_exists($class, self::$classes))
  {
   require_once self::$baseDir.self::$sysClass.self::$classes[$class];
  }
  else
  {
   echo "&nbsp;Класс {$className} не является системным<br>";
   if(file_exists(self::$baseDir.self::$usrClass.$className.self::$classExt))
   {
    require_once self::$baseDir.self::$usrClass.$className.self::$classExt;
   }
   else
   {
    echo "&nbsp;Класс {$className} не является пользовательским.<br>";
    throw new Exception(sprintf("Класс %s не найден.", $className));
    return FALSE;
   }
  }
}
}
?>


при попытке создать экземпляр пока несуществующего в системе класса происходит попытка его найти и загрузить. Если класс будет найден как системный или пользовательский то все проходит нормально, если класс не найден то вызывается ИС
Код: Выделить всё
throw new Exception(sprintf("Класс %s не найден.", $className));

вроде бы все правильно... но вот беда... когда я пытаюсь вызвать static метод несуществующего класса получаю fotal error
при этом выводится вся отладочная информация.
loading class Class1
Класс Class1 не является системным
Класс Class1 не является пользовательским.
Fatal error: Class 'Class1' not found in /srv/www/rcc/web/index.php on line 0

Может кто в курсе как можно отловить эту ИС?
P.S. точнее не отловить а сделать так что бы она не возникала...
мы рождены чтоб сказку сделать кодом
[DD]
Elite
 
Сообщения: 163
Зарегистрирован: 18 мар 2009, 22:18
Откуда: from HELL
Полное имя: Зыков Д.А.

Re: PHP обработка ИС

Сообщение xdsl 29 сен 2010, 21:05

1. насколько понимаю, эта fatal error возникает и без всякого автолоадинга, поэтому непонятно, зачем он здесь приведен
2. если память не изменяет, то исключения, генерируемые в __autoload() - не перехватываются, значит catch-обработку на них (с продолжением нормальной работы программы) уже не повесишь, что грустно
3. и, наконец, самое грустное - catch-обработку на fatal error вообще не повесишь

А может всего-лишь надо, чтобы в браузере не отображались некоторые типы ошибок? тогда - man set_exception_handler()
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: PHP обработка ИС

Сообщение [DD] 30 сен 2010, 12:36

xdsl писал(а):1. насколько понимаю, эта fatal error возникает и без всякого автолоадинга, поэтому непонятно, зачем он здесь приведен
2. если память не изменяет, то исключения, генерируемые в __autoload() - не перехватываются, значит catch-обработку на них (с продолжением нормальной работы программы) уже не повесишь, что грустно
3. и, наконец, самое грустное - catch-обработку на fatal error вообще не повесишь

А может всего-лишь надо, чтобы в браузере не отображались некоторые типы ошибок? тогда - man set_exception_handler()

1. как видно из отладочной информации fatal error возникает уже после попытки выполнить загрузку(из-за этого и приведен код)
2. Исключения генерируемые в автозагрузчике нормально перехватываются(правда как показывает практика пока нет fatal error)
3. да catch не отлавливает fatal error но мне собственно говоря это и не обезательно
P.S. точнее не отловить а сделать так что бы она не возникала...

и если мне не изменяет память то set_exception_handler() тоже не работает с fatal error

еще раз повторюсь что фотал fatal error возникает только в случае
Код: Выделить всё
Class1::method();

если же я создаю екземпляр
Код: Выделить всё
$c = new Class1();

то вылетает мой экзепшен. Это еще раз доказывает пункт 2, и именно по этому спрашивал нельзя ли это как-то обойти.
мы рождены чтоб сказку сделать кодом
[DD]
Elite
 
Сообщения: 163
Зарегистрирован: 18 мар 2009, 22:18
Откуда: from HELL
Полное имя: Зыков Д.А.

Re: PHP обработка ИС

Сообщение xdsl 02 окт 2010, 11:33

Давайте начнем сначала. Во первых, у меня не воспроизводится Ваша ситуация в полном объеме. PHP - 5.2.11
Код: Выделить всё
<?php
function __autoload($class_name) {
echo "Autoloading begin ...<br>";
throw new Exception("Can't loading $class_name!");
}

try
{
$obj  = new Class1();
}
catch (Exception $e)
{
echo $e->getMessage();
}
?>

Получаем:
Код: Выделить всё
Autoloading begin ...
Fatal error: Class 'Class1' not found in /var/www/html/Projects/auto.php on line 16 Call Stack: 0.0002 48380 1. {main}() /var/www/html/Projects/auto.php:0
Причем замена $obj = new Class1(); на Class1::test(); дает ту-же fatal error. Вы-же утверждаете ,что $obj = new Class1(); не генерирует fatal error;

Во вторых, как гласит http://php.net/manual/en/language.oop5.autoload.php,
Prior to 5.3.0, exceptions thrown in the __autoload function could not be caught in the catch block and would result in a fatal error. From 5.3.0+ exceptions thrown in the __autoload function can be caught in the catch block, with 1 provision.
Значит ожидать перехвата юзер-эксепшн не стоит, все зависит от версии PHP. Правда у меня проверка показала, как ни странно, что сгенерированный в __autoload эксепшн все-таки перехватывается:
Код: Выделить всё
<?php
function __autoload($class_name) {
echo "Autoloading begin ...<br>";
class Class1 { }
throw new Exception("Can't loading $class_name!");
}

try
{
$obj  = new Class1();
}
catch (Exception $e)
{
echo "--------------------<br>";
echo $e->getMessage();
}
?>
Возвращает:
Код: Выделить всё
Autoloading begin ...
--------------------
Can't loading Class1!
Кстати, замена $obj = new Class1(); на Class1::test(); дает тот-же результат, эксепшн корректно перехватывается и обрабатывается.

Следующий вариант, возможно Вас устроит, хотя перехват ошибки становится принципиально невозможен (но, как Вы сказали, для Вас это непринципиально):
Код: Выделить всё
<?php
function __autoload($class_name) {
echo "Autoloading begin ...<br>";
die("Can't loading $class_name!");
}
$obj  = new Class1();
?>
Дает
Код: Выделить всё
Autoloading begin ...
Can't loading Class1!
Работает и при замене $obj = new Class1(); на Class1::test();

Таким образом, заменяете генерацию пользовательского эксепшена на die() и подавляете тем самым fatal error. Понятно, что это не более чем костыль, но в отсутствии Вашего кода, достаточного для проверки и моего слабого понимания цели, к которой Вы стремитесь, это все, что можно предложить.
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.

Re: PHP обработка ИС

Сообщение [DD] 03 окт 2010, 23:19

die меня не устроит так как не дает выводить весь стек вызова. Возможно вся проблема именно в том что я не использую try-cache а устанавливаю функцию обработки ч/з set_exception_handler.
мы рождены чтоб сказку сделать кодом
[DD]
Elite
 
Сообщения: 163
Зарегистрирован: 18 мар 2009, 22:18
Откуда: from HELL
Полное имя: Зыков Д.А.

Re: PHP обработка ИС

Сообщение xdsl 04 окт 2010, 11:47

А если перед die() поставить какой-нибудь var_dump(debug_backtrace()) ?
xdsl
 
Сообщения: 1236
Зарегистрирован: 09 дек 2008, 05:16
Откуда: ВЦ ШГПИ
Полное имя: Слинкин Д.А.


Вернуться в Web-технологии

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron