关于PHP 5中的eval的问题

时间:2010-03-20 11:42:44

标签: php eval

我已经做了近一年的PHP工作了,虽然我知道它的用法,但我从未使用过函数eval()。 但是我在SO中发现了很多关于它的问题。所以有人能告诉我一个简单的例子,其中有必要使用eval()吗?这是一个好的还是坏的做法?

7 个答案:

答案 0 :(得分:10)

eval()是实现像Smarty这样的“编译”模板引擎所必需的,它使用自己的语言并在运行时将其编译为php。这类引擎的主要功能通常是

 function render_template($path) {
    $code = file_get_contents($path);
    $php = $this->compile_to_php($code);
    eval($php);
 }

除此之外,每次使用“include”或“require”时,你实际上都在使用“eval” - 所以,实际上,eval是最常用的php结构之一。

答案 1 :(得分:6)

使用eval()是一种不好的做法,如果事实证明是必要的,那通常是潜在设计错误的标志。

我无法想到有必要使用eval()的任何情况。 (即使用其他语言结构无法实现某些功能,或者通过修复损坏的设计无法实现某些功能。)有兴趣了解是否有任何真实案例出现在这里,其中eval实际上 是必要的,否则替代方案会非常复杂

可能需要的唯一实例是执行来自外部源的代码(例如数据库记录)。但这本身就是设计错误IMO。

答案 2 :(得分:4)

错误的应用程序设计总是这样的例子。

答案 3 :(得分:4)

我曾经使用过eval一次。这是一个系统,用户可以使用从底层系统中捕获的常量输入公式。

字符串如:

(N * (G - 2,7)) / E
取出

,然后使用系统eval中的值替换常量来获取值。 eval似乎是最简单的方法。 该语句被过滤为仅允许运算符和大写字母(彼此没有两个),所以这可能不是eval的“真实”用例,但它可以工作并且非常易读。

那说任务中的系统很大(200k +行),这是唯一使用eval的地方。

答案 4 :(得分:3)

命令行php shell就是一个很好的例子。我想你可以分叉实际的PHP代码并在C中编写你的shell扩展,但在php中做它似乎更明智。由于提供代码的人应该已经拥有对系统的完全访问权限,因此根本没有安全问题。一旦你使用readline编译php,这种事情实际上非常有用。

Drupal(可选)使用eval来实现随时可扩展性。为实现此目的,需要评估用户(通常仅限管理员)的代码输入并将其存储在数据库中。 Drupal还有很多人确保没有安全漏洞。

答案 5 :(得分:2)

如果从安全方面看,使用eval是非常危险的。无论如何,很多模板引擎都使用eval,因为它们应该解析页面并获取一些变量或进行计算。

答案 6 :(得分:2)

Eval在这种情况下很有用,例如在wordpress中循环注册小部件 创建自定义主题:

class PluginusNetWPTF_Widget extends PluginusNetWPTF_Core {

    public static $widgets = array(
        'PLUGINUSNET_RECENT_POSTS_WIDGET' => array(
            'description' => 'Recent posts of selected category',
            'creation' => 'PluginusNet Recent Posts',
            'fields' => array('title' => 'Recent Posts', 'category' => '', 'post_number' => 3, 'show_thumbnail' => 1, 'show_exerpt' => 0),
            'view' => 'recent_posts',
            'form' => 'recent_posts_form'
        ),
            //'PLUGINUSNET_RECENT_POSTS_WIDGET2' => array(),
    );

    public static function register_widgets() {
        foreach (self::$widgets as $widget_class_name => $widget_data) {
            $code = '

class '.$widget_class_name.' extends WP_Widget {

    //Widget Setup
    function __construct() {
        //Basic settings
        $settings = array("classname" => __CLASS__, "description" => __(PluginusNetWPTF_Widget::$widgets[__CLASS__]["description"], PLUGINUSNET_THEME_NAME));

        //Creation
        $this->WP_Widget(__CLASS__, __(PluginusNetWPTF_Widget::$widgets[__CLASS__]["creation"], PLUGINUSNET_THEME_NAME), $settings);
    }

    //Widget view
    function widget($args, $instance) {
        $args["instance"] = $instance;
        echo PluginusNetWPTF_Widget::draw_html("widget/" . PluginusNetWPTF_Widget::$widgets[__CLASS__]["view"], $args);
    }

    //Update widget
    function update($new_instance, $old_instance) {
        $instance = $old_instance;
        if (!empty(PluginusNetWPTF_Widget::$widgets[__CLASS__]["fields"])) {
            foreach (PluginusNetWPTF_Widget::$widgets[__CLASS__]["fields"] as $key => $value) {
                $instance[$key] = $new_instance[$key];
            }
        }

        return $instance;
    }

    //Widget form
    function form($instance) {
        //Defaults
        $defaults = PluginusNetWPTF_Widget::$widgets[__CLASS__]["fields"];
        $instance = wp_parse_args((array) $instance, $defaults);
        $args = array();
        $args["instance"] = $instance;
        $args["widget"] = $this;
        echo PluginusNetWPTF_Widget::draw_html("widget/" . PluginusNetWPTF_Widget::$widgets[__CLASS__]["form"], $args);
    }

}

';
            eval($code);
            register_widget($widget_class_name);
        }
    }

}