Web

Применение выражения eval в php

За все годы разработки php я всегда слышал, что использование eval() - недопустимо.

Учитывая следующий код, имеет ли смысл использовать второй (и более элегантный) вариант? Если нет, то почему?

// $type как результат SQL выражения

// то есть SHOW COLUMNS FROM a_table LIKE 'a_column';

// следовательно, нужно быть уверенным в согласованности

// этих строк

$type = "enum('a','b','c')";

// первый вариант

$type_1 = preg_replace('#^enum\s*\(\s*\'|\'\s*\)\s*$#', '', $type);

$result = preg_split('#\'\s*,\s*\'#', $type_1);

// второй вариант

eval('$result = '.preg_replace('#^enum#','array', $type).';');

 

Ответ 1

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

Основные проблемы с eval():

  • Потенциально небезопасный ввод. Передача ненадежного параметра - это способ потерпеть неудачу. Часто бывает нетривиальной задачей удостовериться, что параметру (или его части) полностью доверяют.

  • Смарт подход. Использование eval() делает код умным, поэтому его труднее отслеживать.

Основная проблема с использованием eval() только одна - неопытность разработчиков, которые используют его без должного внимания.

Как правило, необходимо следовать следующим принципам:

  1. Иногда eval() – единственное/правильное решение.

  2. В большинстве случаев следует попробовать что-то другое.

  3. Если не уверены, перейдите к 2.

  4. В ином случае будьте очень и очень осторожны.

 

 Ответ 2

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

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

Ответ 3

Если вы считаете eval() недопустимым решением, тогда его не следует использовать. На мой взгляд, вопрос: «Когда eval() является некорректным решением?», похоже, подразумевает, что недостатки использования eval() волшебным образом исчезают в некоторых контекстах.

Использование eval(), как правило, является плохой идеей, потому что это снижает читаемость кода, способность предсказывать путь кода (и возможные последствия этого для безопасности) до выполнения и, следовательно, ухудшает способность анализировать и отлаживать код. Использование eval() также может предотвратить оптимизацию оцениваемого и окружающего его кода с помощью кэша опкодов, такого как Zend Opcache, интегрированного в PHP 5.5 и выше, или JIT-компилятором, например, в HHVM.

Ответ 4

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

Хотя это не совсем элегантно. Это в основном проблема парсинга текста и злоупотребление парсером PHP для обработки. Если вы хотите злоупотребить языковыми функциями, почему бы не злоупотребить парсером JSON? По крайней мере с парсером JSON вообще нет возможности внедрения кода, например:

$json = str_replace(array(

    'enum', '(', ')', "'"), array)

    '',     '[', ']', "'"), $type);

$result = json_decode($json);

Использование регулярных выражений, вероятно, является наиболее очевидным способом. Вы можете использовать одно регулярное выражение для извлечения всех значений из этой строки:

$extract_regex = '/

    (?<=,|enum\()   # Извлечение строк, которые следуют либо за запятой, либо за строкой "enum("...

    \'      # ...затем открывающая кавычка...

    (.*?)

    \'      # ...вплоть до закрывающей кавычки...

    /x';

preg_match_all($extract_regex, $type, $matches);

$result = $matches[1];

 

Схожие статьи

Что такое визуальная концепция сайта: этапы разработки
Web

Что такое визуальная концепция сайта: этапы разработки

Web

Генератор случайных строк в PHP

Web

Как усечь строку в PHP до слова, ближайшего к определенному количеству символов

Web

Несоответствие токена csrf laravel для запроса POST ajax