Анимация
JavaScript
|
Главная Библионтека Теперь немного о том, как мы будем реализовывать Uses(). Это довольно несложно. Помните, я подчеркивал, что поскольку PHP является интерпретатором, то на нем осуществимы такие приемы, как описание функций внутри функций и многое другое. Так мы и сделаем: функция Uses() вначале будет проверять, не загружался ли уже модуль с таким именем, затем искать затребованный модуль в специальных "каталогах для модулей", фиксировать во внутреннем массиве факт, что указанный файл загружен, и, наконец, вызывать include once для файла с модулем. Кроме того, на время загрузки текущий каталог будет сменяться на тот, в котором находится модуль, чтобы стартовые части всех модулей запускались в "своих" каталогах. Это как раз та возможность, которая отсутствует в Perl, и которая оказывается довольно удобной на практике. Раз библиотекарь всегда подключается к программе в первую очередь, разумно доверить ему выполнение еще некоторых действий. □ Поместим в файл библиотекаря функции, чаще всего необходимые почти каждому сценарию. Таким образом, мы как бы "расширим" набор встроенных в PHP функций. Однако помните, что встроенные функции переопределять все же нельзя, можно лишь создавать новые с уникальными именами. □ Библиотекарь, как никто другой, должен приложить максимум усилий, чтобы сделать сценарии переносимыми с одной платформы на другую. Для нас это будет заключаться в корректировке некоторых переменных, которые PHP создает перед выполнением программы. Первым кандидатом на такую правку будет $SCRIPT NAME (а также одноименная переменная окружения), которая, как мы знаем, в Windows-версии PHP содержит не то значение, которое мы ожидаем. □ И еще нам хочется, чтобы на момент загрузки модуля текущий каталог сменялся на тот, в котором расположен файл модуля. Таким образом, стартовая часть библиотеки всегда сможет определить, где она находится, - например, при помощи вызова getcwd() . Вот что у нас получится в результате: i Листинг 29.1. Библиотекарь: librarian.phi <?if(!defined("LIBRARIAN LOADED")) { define("LIBRARIAN LOADED",1); Расширение библиотечн1х файлов по умолчанию define("LibExt","phl"); Пути поиска библиотек. Если начинаются с точки, то поиск ВСЕГДА ведется относительно текущего каталога, даже если его сменят, в противном случае при следующем вызова Uses() будет в1полнен перевод пути в абсолютн1й. $INC=array(".","./lib"); Функция преобразует указанн1Й относительн1Й путь в абсолютн1Й. Если путь уже является абсолютным ( т. е. отсчитывается от корневого каталога системы), то с ним ничего не происходит, в противном случае используется имя текущего каталога ( или заданного в $cur) с необходим1ми преобразованиями. Существование файла с полученн1м полн1м именем не проверяется. Функция лишена некоторых недостатков встроенной в PHP realpath() и имеет по сравнению с ней несколько большие возможности, работая, правда, чуть медленнее. function GetAbsPath($name,$cur="") { return abs path($name,$cur); } function abs path($name,$cur="") { Преобразуем обратные слэши в прямые $name=strtr(trim($name),"\\","/"); Сначала разбиваем путь по знакам "/" $Parts=explode("/",$name); $Path=($cur===""?getcwd():$cur); начальный каталог поиска foreach($Parts as $i=>$s) if($s!=".") { Признак корневого каталога? if(!$i && (strlen($s)>1&&$s[1]==":"$s=="")) $Path=$s; Ссылка на родительский каталог? elseif($s=="..") { Если это уже корневой каталог, то куда спускаться?.. if(strlen($Path)>1 && $Path[1]==":") continue; Иначе используем dirname() $p=dirname($Path); if($p=="/"$p=="\\"$p==".") $Path=""; else $Path=$p; Иначе просто имя очередного каталога elseif($s!=="") $Path.="/$s"; return ($Path!==""?$Path:"/"); Преобразует URL в абсолютн1Й файлов1Й путь. Т. е. если адрес начинается со слэша, то результат рассматривается по отношению к каталогу DOCUMENT ROOT, а если нет - то относительно dirname($SCRIPT NAME). Конечно, функция не безупречна (например, она не умеет обрабат1вать URL, заданн1е Alias-директивами Apache, но в большинстве случаев это и не нужно. function Url2Path($name) { $curUrl=dirname($GLOBALS["SCRIPT NAME"]); $url=abs path(trim($name),$curUrl); return getenv("DOCUMENT ROOT").$url; Превращает все пути в списке $INC в абсолютн1е, однако делает это не каждый раз, а только если массив изменился с момента последнего вызова. function AbsolutizeINC() { global $INC; static $PrevINC=""; значение $INC при предыдущем входе Сначала проверяем - изменился ли $INC. Если да, то преобразуем все пути в массиве в относительные, иначе ничего не делаем. Нам это нужно только из соображений пов1шения производительности функции. if($PrevINC!==$INC) { не можем использовать foreach, т. к. нам надо модифицировать массив for($i=0; $i<count($INC); { $v=&$INC[$i]; if($v[0]=="." && (strlen($v)==1 $v[1]==\\ $v[1]==/)) continue; $v=abs path($v); Запоминаем текущее состояние массива $PrevINC=$INC; Загружает указанную библиотеку функций. Для поиска файла просматривает каталоги в массиве $INC. function Uses($libname) { global $INC; static $PrevINC=""; значение $INC при предыдущем входе static $LastFound=0; для ускорения работы Переводим все пути в $INC в относительные - вдруг вызывающая программа добавила что-нибудь в массив?.. AbsolutizeINC(); 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 |