Когда (если вообще когда-либо) это не зло? - PullRequest
26 голосов
/ 17 августа 2010

Я слышал много мест , что PHP eval функция часто не является ответом . В свете PHP 5.3 5.3 LSB и замыканий у нас заканчиваются причины зависеть от eval или create_function.

Существуют ли какие-либо мыслимые случаи, когда eval является лучшим (единственным?) Ответом в PHP 5.3?

Этот вопрос не о том, является ли eval злом вообще, как, очевидно, нет.

Сводка ответов:

  • Оценка числовых выражений (или других «безопасных» подмножеств PHP)
  • Модульное тестирование
  • Интерактивная PHP "оболочка"
  • Десериализация доверенных var_export
  • Некоторые языки шаблонов
  • Создание бэкдоров для администраторов и / или хакеров
  • Совместимость с
  • Проверка синтаксиса (возможно, небезопасного)

Ответы [ 15 ]

18 голосов
/ 17 августа 2010

Если вы пишете вредоносное ПО и хотите усложнить жизнь системному администратору, который пытается вычистить вас.По моему мнению, это наиболее распространенный случай использования.

17 голосов
/ 04 ноября 2010

Эрик Липперт суммы превышают три сообщения в блоге.Это очень интересное прочтение.

Насколько я знаю, ниже приведены лишь некоторые из причин, по которым eval используется.

Например, когда вы строите комплексматематические выражения, основанные на пользовательском вводе, или когда вы сериализуете состояние объекта в строку, чтобы его можно было сохранить или передать и восстановить позже.

8 голосов
/ 04 ноября 2010

Основная проблема с eval - это шлюз для вредоносного кода. Таким образом, вы никогда не должны использовать его в контексте, где он может быть использован извне, например, пользовательский ввод.

Один допустимый UseCase будет в Mocking Frameworks.

Пример из PHPUnit_Framework_TestCase::getMock()

// ... some code before

    $mock = PHPUnit_Framework_MockObject_Generator::generate(
      $originalClassName,
      $methods,
      $mockClassName,
      $callOriginalClone,
      $callAutoload
    );

    if (!class_exists($mock['mockClassName'], FALSE)) {
        eval($mock['code']);
    }

// ... some code after

На самом деле в методе генерирования происходит много вещей. В терминах непрофессионалов: PHPUnit примет аргументы к generate и создаст шаблон класса из него. Затем будет eval этот шаблон класса, чтобы сделать его доступным для создания экземпляра. Смысл этого в том, чтобы TestDoubles, конечно же, имитировали зависимости в UnitTests.

5 голосов
/ 06 ноября 2010

Вы можете использовать eval для создания специальных классов:

function myAutoLoad($sClassName){

   # classic part
   if (file_exists($sClassName.'.php'){

      require $sClassName.'.php';

    } else {

      eval("
            class $sClassName{
                public function __call($sMethod,$aArgs){
                     return 'No such class: ' . $sClassName;
                 }
                }");

    }

} 

Хотя, конечно, использование довольно ограничено (некоторые API или, возможно, DI-контейнеры, тестовые среды, ORM, которые имеют дело с базами данных с динамической структурой, кодовые площадки)

4 голосов
/ 17 августа 2010

Если вы пишете сайт, который интерпретирует и выполняет код PHP, как это делает интерактивная оболочка.

...

Я системный парень, это все, что у меня есть.

3 голосов
/ 03 ноября 2010

eval - это конструкция, которую можно использовать для проверки синтаксических ошибок.

Допустим, у вас есть два сценария PHP:

script1.php

<?php
// This is a valid syntax
$a = 1;

script2.php

<?php
// This is an invalid syntax
$a = abcdef

Вы можете проверить наличие синтаксических ошибок, используя eval:

$code1 = 'return true; ?>'.file_get_contents('script1.php');
$code2 = 'return true; ?>'.file_get_contents('script2.php');

echo eval($code1) ? 'script1 has valid syntax' : 'script1 has syntax errors';
echo eval($code2) ? 'script2 has valid syntax' : 'script2 has syntax errors';

В отличие от php_check_syntax (который все равно считается устаревшим и удаляется), код не будет выполняться.

РЕДАКТИРОВАТЬ:

Другой (предпочтительный) вариант - php -l.Вы можете использовать приведенное выше решение, если у вас нет доступа к командам выполнения system () или оболочки.

Этот метод может внедрять классы / функции в ваш код.Обязательно используйте preg_replace вызов или namespace перед тем, как сделать это, чтобы предотвратить их выполнение при последующих вызовах.

Что касается темы OP: Когда (если когда-либо) значение evalНЕ ЗЛО? eval просто не зло.Программисты злые за использование eval без причины.eval может сократить ваш код (математическое выражение выражения, на пример).

2 голосов
/ 09 ноября 2010

Я обнаружил, что бывают моменты, когда большинство функций языка являются полезными.В конце концов, даже GOTO имеет своих сторонников .Eval используется в ряде структур и используется хорошо.Например, CodeIgniter использует eval, чтобы различать иерархию классов реализаций PHP 4 и PHP 5.Плагины для блогов, которые позволяют выполнять PHP-код, безусловно, нуждаются в этом (и эта функция доступна в Expression Engine, Wordpress и других).Я также использовал его для одного веб-сайта, где серия представлений почти идентична, но для каждого из них требовался собственный код, а создание какого-то безумного механизма правил было намного сложнее и медленнее.

Хотя я знаю, что это не PHP, я обнаружил, что eval в Python значительно упрощает реализацию базового калькулятора.

По сути, вот вопрос:

  1. Делает ли eval makeэто легче читать ?Одна из наших главных целей - сообщить другим программистам, что происходило в нашей голове, когда мы писали это.В примере CodeIgniter очень ясно, что они пытались достичь.
  2. Есть ли другой способ?Скорее всего, если вы используете eval (или переменные переменные, или любой другой вид синтаксиса поиска строк или отражения), есть другой способ сделать это.Вы исчерпали свои другие варианты?У вас есть разумно ограниченный набор входных данных?Можно ли использовать оператор switch?

Другие соображения:

  1. Можно ли сделать его безопасным?Есть ли способ, которым случайный кусок кода может попасть в оператор eval?
  2. Можно ли сделать его согласованным?Можете ли вы, учитывая данные, всегда и последовательно производить один и тот же результат?
1 голос
/ 06 ноября 2010

Вы можете использовать eval для создания настройки для добавления кода после установки системы. Обычно, если вы хотите изменить код на сервере, вам нужно будет добавить / изменить существующие файлы PHP. Альтернативой этому было бы сохранить код в базе данных и использовать eval для его выполнения. Вы должны быть уверены, что добавленный код безопасен, хотя.

Думайте об этом как о плагине, только о том, что может делать что угодно ...

Можно подумать о сайте, который позволял бы людям добавлять фрагменты кода, которые пользователи затем могли бы динамически добавлять на свои веб-страницы - без сохранения кода в файловой системе веб-серверов. Хотя вам нужен процесс одобрения ...

1 голос
/ 17 августа 2010

Полагаю, eval следует использовать там, где код должен быть скомпилирован .Я имею в виду такие случаи, как компиляция файлов шаблонов (язык шаблонов в PHP для повышения производительности), компиляция подключаемых модулей, компиляции по соображениям производительности и т. Д.

1 голос
/ 17 августа 2010

Подходящим случаем (учитывая отсутствие простых альтернатив) будет случай, когда доверенные данные сериализованы с var_export, и необходимо их десериализовать.Конечно, он никогда не должен был сериализоваться таким образом, но иногда ошибка уже сделана.

...