Intereting Posts
curl POST-формат для CURLOPT_POSTFIELDS mysql_query () ожидает, что параметр 2 будет ресурсом, строка, указанная в Разбор этой файловой структуры JSON PHP file_get_contents возвращает false будет ли этот cronjob работать? Просто получить URL-адрес изображения из строки в PHP sonataNotificationBundle, электронные письма, которые хранятся в базе данных, но потребитель swiftmailer не запускается, и никакие электронные письма не отправляются Имитировать PHP Включить без PHP Использование JQuery, как мне отправить форму, созданную с помощью AJAX? Создание контейнера в хранилище blob Azure – PHP Как получить данные JSON из Rest API с помощью PHP Curl? PHP simplehtmldom добавления атрибутов Использование php для отображения содержимого на вкладках jquery Как суммировать новую и последнюю вставленную запись с тем же идентификатором и вставить результат в новую запись PHP – конвертировать путь к файловой системе в URL

PHP: эквивалент включения использования eval

Если код тот же, то существует разница между:

include 'external.php';

а также

eval('?>' . file_get_contents('external.php') . '<?php');

В чем разница? Кто-нибудь знает?


Я знаю, что они разные, потому что include работает нормально, и eval дает ошибку. Когда я изначально задал вопрос, я не был уверен, что он дал ошибку во всем коде или просто на моем (и потому, что код был eval , было очень сложно выяснить, что такое ошибка). Однако, после изучения ответа, выясняется, что независимо от того, получаете ли вы ошибку, не зависит от кода в файле external.php , но зависит от ваших настроек php (точнее, short_open_tag ).

После нескольких исследований я выяснил, что было не так. Проблема заключается в том, что <?php является «коротким открывающим тегом» и поэтому будет работать, только если short_open_tag установлен в 1 (в php.ini или что-то подобное). Правильный полный тег <?php , который имеет пробел после второго p.

Таким образом, правильный эквивалент включения:

 eval('?>' . file_get_contents('external.php') . '<?php '); 

Кроме того, вы можете оставить открывающий тег вместе (как указано в комментариях ниже):

 eval('?>' . file_get_contents('external.php')); 

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

 eval('?>' . file_get_contents('external.php') . '<?php;'); 

AFAIK вы не можете использовать ускорители php, если используете eval ().

Если вы используете веб-сервер, на котором вы установили кеш-код операции, например APC , eval не будет « лучшим решением »: код eval'd не хранится в кеше кода операции, если я правильно помню (и еще один ответ сказал, что то же самое, кстати) .

Решение, которое вы могли бы использовать, по крайней мере, если код не часто изменяется, получает соединение кода, хранящегося в базе данных, и включает код:

  • при необходимости, получить код из БД и сохранить его в файле на диске
  • включить этот файл
  • поскольку код теперь находится в файле, на диске, кеш-код операции может кэшировать его – что лучше для выполнения
  • и вам не нужно будет делать запрос в БД каждый раз, когда вам нужно выполнить код.

Я работал с программным обеспечением, использующим это решение (файл на диске был не более чем кешем кода, хранящимся в БД), и я работал не так уж плохо – лучше, чем при загрузке запросов БД каждой страницы, так или иначе…

Некоторые не очень хорошие вещи, как следствие:

  • вам нужно извлечь код из БД, чтобы поместить его в файл «при необходимости»,
    • это может означать повторное создание временного файла один раз в час или удаление его при изменении записи в БД? У вас есть способ определить, когда это произойдет?
  • вам также необходимо изменить свой код, использовать временный файл или, если необходимо, повторно сгенерировать его
    • если у вас есть несколько мест для модификации, это может означать некоторую работу

Кстати: я бы смел сказать что-то вроде «eval is evil»?

Как заметил @bwoebi в этом ответе на мой вопрос , подстановка eval не учитывает контекст пути файла включенного файла. В качестве тестового примера:

Baz.php :

 <?php return __FILE__; 

Foo.php :

 <?php echo eval('?>' . file_get_contents('Baz.php', FILE_USE_INCLUDE_PATH)) . "\n"; echo (include 'Baz.php') . "\n"; 

Результат выполнения php Foo.php :

 $ php Foo.php /path/to/file/Foo.php(2) : eval()'d code /path/to/file/Baz.php 

Я не знаю, как изменить константу __FILE__ и друзей во время выполнения, поэтому я не думаю, что существует общий способ определения include с точки зрения eval .

Только eval('?>' . file_get_contents('external.php')); вариант – правильная замена для включения.

См. Тесты:

 <?php $includes = array( 'some text', '<?php print "some text"; ?>', '<?php print "some text";', 'some text<?php', 'some text<?php ', 'some text<?php;', 'some text<?php ?>', '<?php ?>some text', ); $tempFile = tempnam('/tmp', 'test_'); print "\r\n" . "Include:" . "\r\n"; foreach ($includes as $include) { file_put_contents($tempFile, $include); var_dump(include $tempFile); } unlink($tempFile); print "\r\n" . "Eval 1:" . "\r\n"; foreach ($includes as $include) var_dump(eval('?>' . $include . '<?php ')); print "\r\n" . "Eval 2:" . "\r\n"; foreach ($includes as $include) var_dump(eval('?>' . $include)); print "\r\n" . "Eval 3:" . "\r\n"; foreach ($includes as $include) var_dump(eval('?>' . $include . '<?php;')); 

Вывод:

 Include: some textint(1) some textint(1) some textint(1) some text<?phpint(1) some textint(1) some text<?php;int(1) some textint(1) some textint(1) Eval 1: some textNULL some textNULL bool(false) some text<?phpNULL bool(false) some text<?php;NULL some textNULL some textNULL Eval 2: some textNULL some textNULL some textNULL some text<?phpNULL some textNULL some text<?php;NULL some textNULL some textNULL Eval 3: some text<?php;NULL some text<?php;NULL bool(false) some text<?php<?php;NULL bool(false) some text<?php;<?php;NULL some text<?php;NULL some text<?php;NULL 

Это позволяет вам включать файл, предполагающий, что файловые оболочки для включений включены в PHP:

 function stringToTempFileName($str) { if (version_compare(PHP_VERSION, '5.1.0', '>=') && strlen($str < (1024 * 512))) { $file = 'data://text/plain;base64,' . base64_encode($str); } else { $file = Utils::tempFileName(); file_put_contents($file, $str); } return $file; } 

… Затем включите этот файл. Да, это также отключит кэши кода операций, но это делает этот «eval» таким же, как включение в отношении поведения.

вот мой подход.

он создает временный файл php и включает его.

но таким образом, если код, который вы хотите запустить на этой функции, имеет ошибки выхода программ перед удалением временного файла

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

Я также добавил параметр игнорирования ошибки для решения не удаленных временных файлов. если ошибки игнорируются, программа продолжит работу и удалит временный файл.

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

 function eval2($c) { $auto_clean_old_temporary_files=false; //checks old temporary eval2 files for this spesific temporary file names generated by settings below $ignore_all_errors=true; //if you ignore errors you can remove temporary files even there is an error $tempfiledirectory=''; //temporary file directory $tempfileheader='eval2_'; // temporary file header $tempfiletimeseperator='__'; // temporary file seperator for time $tempfileremovetimeout=200; // temp file cleaning time in seconds if ($auto_clean_old_temporary_files===true) { $sd=scandir('.'); //scaning for old temporary files foreach ($sd as $sf) { if (strlen($sf)>(32+strlen($tempfileheader)+strlen($tempfiletimeseperator)+3)) { // if filename long enough $t1=substr($sf,(32+strlen($tempfileheader)),strlen($tempfiletimeseperator)); //searching time seperator $t2=substr($sf,0,strlen($tempfileheader)); //searching file header if ($t1==$tempfiletimeseperator && $t2==$tempfileheader) { //checking for timeseperator and file name header $ef=explode('.',$sf); unset($ef[count($ef)]);//removing file extension $nsf=implode('.',$ef);//joining file name without extension $ef=explode($tempfiletimeseperator,$nsf); $tm=(int)end($ef); //getting time from filename $tmf=time()-$tm; if ($tmf>$tempfileremovetimeout && $tmf<123456 && $tmf>0) { // if time passed more then timeout and difference with real time is logical unlink($sf); // finally removing temporary file } } } } } $n=$tempfiledirectory.$tempfileheader . md5(microtime().rand(0,5000)). $tempfiletimeseperator . time() .'.php'; //creating spesific temporary file name $c='<?php' . PHP_EOL . $c . PHP_EOL; //generating php content file_put_contents($n,$c); //creating temporary file if ($ignore_all_errors===true) { // including temporary file by your choise $s=@include($n); }else{ $s=include($n); } return $s; }