代码之家  ›  专栏  ›  技术社区  ›  Jasper

PHP:相当于使用eval的include

  •  14
  • Jasper  · 技术社区  · 16 年前

    如果代码相同,则以下各项之间似乎存在差异:

    include 'external.php';

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

    有什么区别?有人知道吗?


    我知道这两者是不同的,因为 include 工作很好,而且 eval 评估 ed,很难找出错误的含义)。然而,在研究了答案之后,结果表明,您是否得到错误并不取决于 external.php ,但这取决于您的php设置( short_open_tag

    8 回复  |  直到 11 年前
        1
  •  14
  •   Jasper    13 年前

    经过更多的研究,我自己发现了问题所在。问题在于 <?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;');
    
        2
  •  6
  •   niteria    16 年前

    如果使用eval(),那么就不能利用php加速器。

        3
  •  6
  •   Pascal MARTIN    16 年前

    如果您使用的是安装了操作码缓存的Web服务器,如 APC , eval 最佳解决方案 “:如果我没记错的话,评估代码没有存储在操作码缓存中 (顺便说一句,另一个答案也是如此)

    至少在代码不经常更改的情况下,您可以使用的解决方案是混合使用存储在数据库中的代码和包含的代码:

    • 必要时,从数据库中获取代码,并将其存储在磁盘上的文件中
    • 由于代码现在位于磁盘上的文件中,操作码缓存将能够缓存它——这对性能更有利

    我曾经使用过使用此解决方案的软件(磁盘上的文件只不过是数据库中存储的代码的缓存),我的工作还不错——无论如何,比加载每个页面的数据库请求要好得多。。。

    • 您必须从数据库中获取代码,以便在“必要时”将其放入文件中
      • 这可能意味着每小时重新生成一次临时文件,或者在修改DB中的条目时删除它?你有办法确定这种情况何时发生吗?
    • 您还必须更改代码,使用临时文件,或者在必要时重新生成它
      • 如果你有几个地方需要修改,这可能意味着一些工作

        4
  •  2
  •   Community Mohan Dere    9 年前

    this answer to my question ,即 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 依据 评估

        5
  •  1
  •   Jaimie Sirovich    16 年前

    这允许您在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;
    }
    

        6
  •  1
  •   Mihail H.    12 年前

    只有 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
    
        7
  •  1
  •   Community Mohan Dere    5 年前

    关于上述解决方案的一些想法:

    临时文件

    不要。这对性能非常不利,只是不要这样做。它不仅使您的操作码缓存完全疯狂(缓存命中从未发生+每次都尝试再次缓存),而且还让您头痛的是在高(甚至中等)负载下文件系统锁定,因为您必须写入文件,Apache/PHP必须读取文件。

    简单评估()

    少数情况下可接受;不要经常这样做。事实上,它没有被缓存(糟糕的操作码缓存只是不知道它和以前是同一个字符串);同时,如果您的代码是

    内存中的eval()

    事实上,eval是 很快 在不进行文件操作的情况下对同一事物求值两次 ,这是非常重要的。如果您将它用于不断变化的、小的、内存生成的字符串,那么很明显,选择它是eval——与迭代的include()相比,一次又一次地加载+eval要快很多倍。

    TL;博士

    • 相同的代码,每个请求一次: 包括
    • 评估
    • 评估
        8
  •  0
  •   minaretsbayonet    8 年前

    这是我的方法。

    它创建并包含临时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;  
    
    }
    
    推荐文章