关于PHP5中eval的问题
我做PHP已经快一年了,我从来没有使用过函数关于PHP5中eval的问题,php,eval,Php,Eval,我做PHP已经快一年了,我从来没有使用过函数eval(),尽管我知道它的用法。 但是我在SO中发现了很多关于它的问题。那么有人能给我举个简单的例子,说明有必要使用eval()?这是一种好的做法还是一种坏的做法?使用eval()是一种坏的做法,如果结果证明有必要实现某些东西,这通常是潜在设计错误的标志 我想不出有什么情况需要使用eval()。(即,使用其他语言构造或修复损坏的设计无法实现的东西。)有兴趣看看是否出现了任何真正的案例,其中eval实际上是必要的,或者替代方案会非常复杂 唯一需要它的实
eval()
,尽管我知道它的用法。
但是我在SO中发现了很多关于它的问题。那么有人能给我举个简单的例子,说明有必要使用eval()
?这是一种好的做法还是一种坏的做法?使用eval()
是一种坏的做法,如果结果证明有必要实现某些东西,这通常是潜在设计错误的标志
我想不出有什么情况需要使用eval()
。(即,使用其他语言构造或修复损坏的设计无法实现的东西。)有兴趣看看是否出现了任何真正的案例,其中eval实际上是必要的,或者替代方案会非常复杂
唯一需要它的实例是执行来自外部源(例如数据库记录)的代码,但这本身就是一个设计错误。糟糕的应用程序设计总是这样一个例子。我曾经使用过eval。这是一个系统,用户可以使用从底层系统中获取的常量输入公式 像这样的字符串:
(N * (G - 2,7)) / E
然后使用系统评估中的值替换常量以获取值。评估似乎是最简单的方法。
该语句被过滤为只允许运算符和大写字母(没有两个相邻),因此这可能不是eval的“真实”用例,但它可以工作并且可读性很好
也就是说,任务中的系统非常庞大(超过200k行),这是唯一使用eval的地方。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构造之一。如果从安全角度看,使用eval是相当危险的。无论如何,很多模板引擎都使用eval,因为它们应该解析页面并获取一些变量或进行计算。命令行php shell就是一个很好的例子。我想您可以使用实际的php代码,用C编写shell扩展,但用php编写shell扩展似乎更明智。因为提供代码的人应该已经拥有对系统的完全访问权限,所以根本没有安全问题。一旦用readline编译了php,这类东西实际上非常有用
Drupal(可选)使用eval来支持现成的可扩展性。要实现这一点,需要用户(通常仅限管理员)输入要评估的代码并将其存储在数据库中。Drupal也有很多人来确保没有安全漏洞。评估在这种情况下很有用,例如在wordpress中注册cycle中的小部件 创建自定义主题:
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);
}
}
}
但是,如果在我们自己的代码中使用,这似乎是不好的做法,是吗?:)好吧,我认为99%的人谈论“不好的做法”都无法解释原因。他们只是重复他们从别人那里听到的废话。但这不是“必要的”,如果你想的话,还有其他方法可以实现。把“坏习惯”变成一个循环论证:如果99%的人不能解释原因,那么几乎同样数量的人不能决定何时(以及如何)使用eval()是安全的,并且应该远离它,这难道不是一个安全的赌注吗?+1因为“坏习惯”无法解释原因。他们只是重复他们从别人那里听到的胡说八道。.+1用于消除毫无意义的短语“糟糕做法”的神秘性-任何时候当你调用
require
或include
时,你实际上已经在幕后使用了eval()。例如表达式解析。虽然很少见,但我已经做过很多次了。当然,它是一个复杂而完整的表达式,而不是用最多圆括号支持的常规数学。这就是说,eval上通常的预防措施总是适用的:它们很慢(缓存结果修复),可能不必要(在我的情况下不是这样),并且存在安全问题(但是,相关代码由系统管理员自己运行,因此不是问题)。