Анимация
JavaScript
|
Главная Библионтека передача функций "по ссылке" Я отнюдь не случайно заключил последние два слова названия этого раздела в кавычки - дело в том, что как таковая, передача функции по ссылке в PHP не поддерживается. Однако, т. к. это слишком часто может быть полезным, в PHP есть понятие "функциональной переменной". Легче всего его можно рассмотреть на примеiр.ах : A($i) { echo "a $i\n"; } function B($i) { echo "b $i\n"; } function C($i) { echo "c $i\n"; } $F="A"; или $F="B" или $F="C" $F(10); вызов функции, имя которой хранится в $F Второй пример носит довольно прикладной характер. В PHP есть такая стандартная функция - uasort() , которая сортирует ассоциативный массив, заданный ее первым параметром, причем критерием сравнения для элементов этого массива служит функция, имя которой передано вторым параметром. Мы уже рассматривали эту функцию в предыдущей главе, но я еще раз приведу простой пример: Сравнение без учета регистра символов строк function FCmp($a,$b) { return strcmp(tolower($a),tolower($b)) $a=array("b"=>"bbb", "a"=>"Aaa", "d"=>"ddd); uasort($a,"FCmp"); Сортировка без учета регистра символов Здесь функция, имя которой получено со вторым параметром uasort(), должна иметь два аргумента, которые являются сравниваемыми значениями в массиве. В общем случае, функциональная переменная - это всего лишь переменная-строка, содержащая имя функции, и ничего больше. Поскольку в PHP нет такого понятия, как области видимости для функций (есть только области видимости для локальных переменных), то конфликтов это не порождает - одному имени может соответствовать эти директивы обрабатываются во время компиляции, а в PHP - во время выполнения. Что ж, на то он и интерпретатор, чтобы позволять себе интерпретацию. Примечание То, что возможно создавать условно определяемые функции, сильно подрывает веру в PHP как в истинный транслятор. Как вообще можно устроить транслятор так, чтобы он правильно обрабатывал подобные вещи? Я не знаю. Надеюсь, что разработчики PHP нашли-таки способ, и условно определяемые функции транслируются вместе со всей программой, а не на этапе исполнения, как это было в PHP версии 3. Однако полной уверенности в этом нет, а документация по этому поводу молчит (пока). возврат функцией ссылки До сих пор я рассматривал лишь функции, которые возвращают определенные значения - а именно, копии величин, использованных в инструкции return. Заметьте, это были именно копии, а не сами объекты. Например: $a=100; function R() { global $a; объявляет $a глобальной return $a; возвращает заене, а не сс1лку! $b=R(); $b=0; присваивает $b, а не $a! echo $a; выводит 100 В то же время мы бы хотели, чтобы функция R() возвращала не величину, а ссглку на переменную $a, чтобы в дальнейшем с этой ссылкой можно было работать точно так же, как и с $a. Например, это может очень пригодиться в объектно-ориентированном программировании на PHP (основы которого мы рассмотрим в пятой части книги), когда функция должна возвращать именно объект, а не его копию. Как же нам добиться нужного результата? Использование оператора $b=&R(), к сожалению, не подходит, т. к. при этом мы получим в $b ссылку не на $a, а на ее копию. Если задействовать return &$a, то появится сообщение о синтаксической ошибке (PHP воспринимает & только в правой части оператора присваивания сразу после знака =). Но выход есть. Воспользуемся специальным синтаксисом описания функции, возвращающей ссылку (листинг 11.15): ! Листинг 11.15. Возвращение ссылки $a=100; function &R() & - возвращает сс1лку { global $a; объявляет $a глобальной return $a; возвращает заене, а не сс1лку! $b=&R(); не забудьте & !!! $b=0; присваивает переменной $a! echo $a; в1водит 0. Это значит, что теперь $b - синоним $a не более одной функции. Такой подход, на мой взгляд, не очень хорош, но он действительно работает, и это главное. Лично я не нахожу такой синтаксис удобным. Достаточно по-ошибке всего один раз пропустить & при вызове функции, как переменной $b будет присвоена не ссылка на $a, а только ее копия со всеми вытекающими из этого последствиями. При использовании объектно-ориентированного программирования это может породить логические ошибки, выглядящие крайне странно. Поэтому я рекомендую применять возврат ссылки как можно реже, и только в тех случаях, когда это действительно необходимо. пример функции: Dump() В отладочных целях часто бывает нужно посмотреть, что содержит та или иная переменная. Однако, если эта переменная - массив, да еще многомерный, с выводом ее содержимого на экран могут возникнуть проблемы. Решить их призвана следующая функция, которую я назвал Dump(). Пользу от этой функции можно реально почувствовать, лишь поработав с ней некоторое время. Уверяю, потом вы не сможете понять, как раньше без нее обходились Функция выводит содержимое любой, сколь угодно сложной, переменной, будь то массив, объект или простая переменная. Как уже говорилось, приведенная функция исключительно полезна при отладке сценариев (которая в PHP пока еще не особенно развита). ( Замечание В PHP версии 4 для аналогичных целей существуют две стандартных функции - print r() и var dump(), но листинг, который они выводят, довольно неудобен для восприятия человеком. Листинг 11.16. Функция Dump() Вспомогательная функция, делающая всю "грязную" работу function TextDump(&$Var,$Level=0) { if(is array($Var)) $Type="Array[".count($Var)."]"; else if(is object($Var)) $Type="Object"; else $Type=""; if($Type) { echo "$Type\n"; for(Reset($Var),$Level++; list($k,$v)=each($Var);) { if(is array($v) && $k==="GLOBALS") continue; Как видим, нужно поставить & в двух местах: перед определением имени функции, а также в правой части оператора присваивания при вызове функции. Использовать амперсанд в инструкции return не нужно. 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 |