Анимация
JavaScript
|
Главная Библионтека Теперь просматриваем пути, начиная с того, по которому была найдена какая-нибудь пред1дущая загруженная библиотека. Скорее всего, там окажется загружаем1Й сейчас модуль. Если нет - что же, просмотрим весь список... $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); Ничего не в1шло - "умираем"... die("Couldnt 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")) ( Замечание Возможно, вы скажете, что то же самое можно было бы сделать и в модулях, и обойтись вообще без библиотекаря. Однако это приведет к заметной потере производительности, потому что интерпретатору каждый раз придется загружать и разбирать весь файл модуля, а это - основное время при запуске программы. Пожалуй, в приведенном коде есть и еще одно интересное место. Я имею в виду инструкции, помеченные комментарием: "Делаем доступными для модуля все глобальные переменные". Зачем это нужно? Разве глобальные переменные по определению не доступны подключаемому модулю? К сожалению, это так, и вот почему. Мы вызываем include once в теле функции Uses(), а не в глобальном контексте. Неудивительно, что подключенный файл работает не в нем, а в области видимости тела функции. Указанный цикл перебора всех глобальных переменных и их "глобализация" с помощью global решает проблему. ( Замечание Здесь есть еще одна тонкость. Если модуль "захочет" определить какую-либо новую глобальную переменную, он не сможет сделать это никак иначе, чем через массив $globals. Однако изменять имеющиеся переменные напрямую он все же способен. Работа с библиотекарем Рассмотрим пример сценария, использующего библиотекарь в своей работе. Мы будем предполагать, что все модули размещены в подкаталоге /lib основного каталога На всякий случай включаем максимальный контроль ошибок Error reporting(1+2+4+8); ВНИМАНИЕ! После следующего закр1вающего тэга не должно быть НИКАКИХ ПРОБЕЛОВ! В противном случае сценарий, подключающий библиотекаря, будет выводить в самом начале своей работы этот пробел, что недопустимо при работе с Cookies. }?> Обратите внимание на то, что весь код библиотекаря помещен в блок оператора if. Это сделано специально, чтобы при возможной (ошибочной) повторной загрузке библиотекаря по include все работало корректно. ( Замечание Пока мы будем подключать библиотекаря явно - инструкцией include. Конечно, это не очень удобно. Очень скоро мы узнаем, как избавиться от указанного недостатка. Пусть сценарию требуется библиотека files.phl, которую мы написали (или где-то достали, хотя модули для PHP все еще большая редкость), и которая содержит некоторые функции для работы с файлами. Примечание Кстати, модулю files.phl самому могут понадобиться некоторые модули. Если это так, нет проблем: достаточно лишь поставить вызов Uses() внутрь кода библиотеки. ! Листинг 29.2. Тестовый сценарий <? include "$DOCUMENT ROOT/lib/librarian.phl"; подключаем библиотекарь Uses("files"); подключаем модуль files.phl Все - теперь можно использовать модуль $Content=ReadAllFile("myfile.txt"); читаем весь файл myfile.txt $Hash=ReadKeyValFile("keyval.txt"); читаем файл формата key=value ... и другие функции, которые, возможно, присутствуют в модуле ?> Как видите, ничего сложного. Давайте теперь посмотрим, как выглядит модуль files.phl. Листинг 29.3. Пример модуля files.phl <? Внимание! Так указывается дополнительный каталог для поиска модулей. Запись означает, что библиотекарь должен искать модули также и в подкаталоге OtherModules/dk текущего каталога $INC[]="OtherModules/dk"; Подключение каких-то других модулей, в которых нуждается files.phl Uses("SomeOtherModule"); Uses("AndOtherModuleToo"); с Web-документами (если вы заметили, такой каталог уже есть в путях поиска модулей по умолчанию, "зашитых" в библиотекаре). 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 [ 133 ] 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |