| |
ив?..
AbsolutizeINC();
Часть V. Приемы программирования на PHP
402
// Теперь просматриваем пути, начиная с того, по которому была
// найдена какая-нибудь предыдущая загруженная библиотека. Скорее
// всего, там окажется загружаемый сейчас модуль. Если нет —
// что же, просмотрим весь список...
$l=$LastFound;
do {
// В очередном каталоге есть файл модуля?..
$dir=$INC[$LastFound];
if(@is_file($file="$dir/$libname.".LibExt)) {
// Сменить каталог на тот, в котором расположен модуль
$cwd=getcwd();
chdir(dirname($file));
// Делаем доступными для модуля все глобальные переменные
foreach($GLOBALS as $k=>$v) global $$k;
// Включаем файл
$ret=include_once($file);
// Пока не вернулись в предыдущий каталог, перевести
// добавленные (возможно?) пути в $INC в абсолютные
AbsolutizeINC();
// Вернуться
chdir($cwd);
return $ret;
}
$LastFound=($LastFound+1)%count($INC);
} while($LastFound!=$l);
// Ничего не вышло — "умираем"...
die("Couldn't find library \"$libname\" at ".join(", ",$INC)."!");
}
// Корректируем некоторые переменные окружения, которые могут иметь
// неверные значение, если PHP установлен не как модуль Apache
@putenv("SCRIPT_NAME=".
$GLOBALS["HTTP_ENV_VARS"]["SCRIPT_NAME"]=
$GLOBALS["SCRIPT_NAME"]=
ereg_Replace("\\?.*","",getenv("REQUEST_URI"))
);
@putenv("SCRIPT_FILENAME".
$GLOBALS["HTTP_ENV_VARS"]["SCRIPT_FILENAME"]=
$GLOBALS["SCRIPT_FILENAME"]=
Url2Path(getenv("SCRIPT_NAME"))
Глава 29. Модульность программы. Написание "библиотекаря"
403
);
// На всякий случай включаем максимальный контроль ошибок
Error_reporting(1+2+4+8);
// ВНИМАНИЕ! После следующего закрывающего тэга
// не должно быть НИКАКИХ ПРОБЕЛОВ! В противном случае
// сценарий, подключающий библиотекаря, будет выводить в самом
// начале своей работы этот пробел, что недопустимо при
// работе с Cookies.
}?>
Обратите внимание на то, что весь код библиотекаря помещен в блок оператора if.
Это сделано специально, чтобы при возможной (ошибочной) повторной загрузке биб-
лиотекаря по include все работало корректно.
Возможно, вы скажете, что то же самое можно было бы сделать и в модулях, и
обойтись вообще без библиотекаря. Однако это приведет к заметной потере
производительности, потому что интерпретатору каждый раз придется загру-
жать и разбирать весь файл модуля, а это — основное время при запуске про-
граммы.
Пожалуй, в приведенном коде есть и еще одно интересное место. Я имею в виду ин-
струкции, помеченные комментарием: "Делаем доступными для модуля все глобаль-
ные переменные". Зачем это нужно? Разве глобальные переменные по определению
не доступны подключаемому модулю? К сожалению, это так, и вот почему. Мы вы-
зываем include_once в теле функции Uses(), а не в глобальном контексте. Неуди-
вительно, что подключенный файл работает не в нем, а в области видимости тела
функции. Указанный цикл перебора всех глобальных переменных и их "глобализа-
ция" с помощью global решает проблему.
Здесь есть еще одна тонкость. Если модуль "захочет" определить какую-либо
новую глобальную переменную, он не сможет сделать это никак иначе, чем
через массив $GLOBALS. Однако изм
|
|