| |
ние оператором return (как, например, это обычно делают функции), eval()
также вернет эту величину.
Параметр $st представляет собой обычную строку, содержащую участок PHP-
программы. То есть в ней может быть все, что допустимо в сценариях:
r ввод-вывод, в том числе закрытие и открытие тэгов и ?>;
r управляющие инструкции: циклы, условные операторы и т. д.;
r объявления и вызовы функций;
r вложенные вызовы функции eval().
Тем не менее, нужно помнить несколько важных правил.
r Код в $st будет использовать те же самые глобальные переменные, что и вы-
звавшая программа. Таким образом, переменные не локализуются внутри
eval().
r Любая критическая ошибка (например, вызов неопределенной функции) в коде
строки $st приведет к завершению работы всего сценария (разумеется, сообще-
ние об ошибке также напечатается в браузер). Это значит, что мы не можем пере-
хватить все ошибки в коде, вставив его в eval().
Последний факт вызывает довольно удручающие мысли. К сожалению, разра-
ботчики PHP опять не задумались о том, как было бы удобно, если бы eval()
при ошибке в вызванном ей коде просто возвращала значение false, поме-
щая сообщение об ошибке в какую-нибудь переменную (как это сделано, на-
пример, в Perl).
Часть IV. Стандартные функции PHP 340
r Тем не менее, синтаксические ошибки и предупреждения, возникающие при
трансля-
ции кода в $st, не приводят к завершению работы сценария, а всего лишь вызывают
возврат из eval()значения ложь. Что ж, хоть кое-что.
Не забывайте, что переменные в строках, заключенных в двойные кавычки, в PHP
интерполируются (то есть заменяются на соответствующие значения). Это значит,
что, если мы хотим реже использовать обратные слэши для защиты символов-
кавычек, нужно стараться применять строки в апострофах для параметра,
передавае-
мого eval(). Например:
eval("$a=$b;"); // Неверно!
// Вы, видимо, хотели написать следующее:
eval("\$a=\$b");
// но короче будет так:
eval('$a=$b');
Возможно, вы спросите: зачем нам использовать eval(), если она занимается лишь
выполнением кода, который мы и так можем написать прямо в нужном месте про-
граммы? Например, следующий фрагмент
eval('for($i=0; $i<10; $i++) echo $i; ');
эквивалентен такому коду:
for($i=0; $i<10; $i++) echo $i;
Почему бы всегда не пользоваться последним фрагментом? Да, конечно, в нашем
примере лучше было бы так и поступить. Однако сила eval() заключается прежде
всего в том, что параметр $st может являться (и чаще всего является) не
статической
строковой константой, а сгенерированной переменной. Вот, например, как мы можем
создать 100 функций с именами Func1()...Func100(), которые будут печатать
квадраты первых 100 чисел:
Листинг 24.1. Генерация семейства функций
for($i=1; $i<=100; $i++)
eval("function Func$i() { return $i*$i; }");
Попробуйте-ка сделать это, не прибегая к услугам eval()!
Я уже говорил, что в случае ошибки (например, синтаксической) в коде, обрабаты-
ваемом eval(), сценарий завершает свою работу и выводит сообщение об ошибке в
браузер. Как обычно, сообщение сопровождается указанием того, в какой строке
про-
изошла ошибка, однако вместе с именем файла выдается уведомление, что програм-
ма оборвалась в функции eval(). Вот как, например, может выглядеть такое сооб-
щение:
Parse error: parse error in eval.php(4) : eval()'d code on line 1
Глава 24. Управление интерпретатором 341
Как видим, в круглых скобках после имени файла PHP печатает номер строки, в ко-
торой была вызвана сама функция eval(), а после "on line" — номер строки в
параметре eval() $st. Впрочем, мы никак не можем перехватить эту ошибку, по-
этому последнее нам не особенно-то интересно.
Давайте теперь в качестве тренировки напишем код, являющийся аналогом инструк-
ции include. Пусть нам нужно включить файл, имя которого хранится в $fname.
Вот как это будет выглядеть:
$code=join("",File($fname));
eval("?>$code");
Всего две строчки, но какие...… Рассмотрим их подробнее.
Что делает
|
|