php extract() 有什么问题?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/829407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is so wrong with extract()?
提问by barfoon
I was recently reading this thread, on some of the worst PHP practices.
In the second answer there is a mini discussion on the use of extract(), and im just wondering what all the huff is about.
我最近读此线程,在一些最严重的PHP的做法。在第二个答案中有一个关于 使用的小型讨论extract(),我只是想知道所有的愤怒是什么。
I personally use it to chop up a given array such as $_GETor $_POSTwhere I then sanitize the variables later, as they have been conveniently named for me.
我个人使用它来切碎给定的数组,例如$_GET或$_POST然后我稍后清理变量的位置,因为它们已经方便地为我命名。
Is this bad practice? What is the risk here? What are your thoughts on the use of extract()?
这是不好的做法吗?这里有什么风险?你对使用有extract()什么想法?
回答by nickf
I find that it is only bad practice in that it can lead to a number of variables which future maintainers (or yourself in a few weeks) have no idea where they're coming from. Consider this scenario:
我发现这只是不好的做法,因为它会导致许多变量,未来的维护者(或几周后的你自己)不知道它们来自哪里。考虑这个场景:
extract($someArray); // could be $_POST or anything
/* snip a dozen or more lines */
echo $someVariable;
Where did $someVariablecome from? How can anyone tell?
哪儿$someVariable来的呢?怎么会有人说
I don't see the problem in accessing the variables from within the array they started in, so you'd really need to present a good case forusing extract()for me to think it's worth it. If you're really concerned about typing out some extra characters then just do this:
我看不出在从阵列中访问这些变量,他们开始在这个问题,那么你真的需要展示一个良好的情况下,对使用extract()我认为这是值得的。如果您真的很担心输入一些额外的字符,那么只需执行以下操作:
$a = $someLongNameOfTheVariableArrayIDidntWantToType;
$a['myVariable'];
I think the comments here on the security aspects of it are overblown somewhat. The function can take a second parameter that actually gives you fairly good control over the newly created variables, including not overwriting any existing variables (EXTR_SKIP), ONLY overwriting existing variables (so you can create a whitelist) (EXTR_IF_EXISTS), or adding prefixes to the variables (EXTR_PREFIX_ALL).
我认为这里关于它的安全方面的评论有些夸大其词。该函数可以采用第二个参数,实际上可以让您对新创建的变量进行相当好的控制,包括不覆盖任何现有变量 ( EXTR_SKIP)、仅覆盖现有变量(因此您可以创建白名单) ( EXTR_IF_EXISTS) 或为变量添加前缀( EXTR_PREFIX_ALL).
回答by dr Hannibal Lecter
Come on now. People blame the tool instead of the user.
现在来吧。人们责怪工具而不是用户。
That's like talking against unlink()because you can delete files with it. extract()is a function like any other, use it wisely and responsibly. But don't claim it's bad per se, that's just ignorant.
这就像反对,unlink()因为你可以用它删除文件。extract()与其他任何功能一样,请明智且负责任地使用它。但不要说它本身不好,那只是无知。
回答by stefs
the risk is: don't trust data from users, and extracting into the current symbol table means, your variables could be overwritten by something the user provides.
风险是:不要相信来自用户的数据,并且提取到当前符号表中意味着,您的变量可能会被用户提供的内容覆盖。
<?php
$systemCall = 'ls -lh';
$i = 0;
extract($_GET);
system($systemCall);
do {
print_r($data[$i];
$i++;
} while ($i != 3);
?>
(a nonsensical example)
(无意义的例子)
but now a malicious user who guesses or knows the code calls:
但是现在猜测或知道代码的恶意用户会调用:
yourscript.php?i=10&systemCall=rm%20-rf
instead of
代替
yourscript.php?data[]=a&data[]=b&data[]=c
now, $systemCall and $i are overwritten, resulting in your script deleting your data first and hanging then.
现在, $systemCall 和 $i 被覆盖,导致您的脚本首先删除您的数据然后挂起。
回答by Jamol
There is nothing wrong with it. Otherwise it wouldnt be implemented. Many (MVC) frameworks use it when you pass (assign) variables to Views. You just need to use it carefully. Sanitize those arrays before passing it to extract() and make sure it does not override your variables. Dont forget that this function also accepts a few more arguments! Using the second and third arguments you can control the behavior if collision occurs. You can override, skip or add prefix. http://www.php.net/extract
没有什么问题。否则就不会实施。许多 (MVC) 框架在您将变量传递(分配)给视图时使用它。你只需要小心使用它。在将它们传递给 extract() 之前清理这些数组,并确保它不会覆盖您的变量。不要忘记这个函数还接受更多的参数!使用第二个和第三个参数可以控制发生碰撞时的行为。您可以覆盖、跳过或添加前缀。 http://www.php.net/extract
回答by SeanDowney
If not used carefully it can confuse the heck out of others you work with consider:
如果不小心使用,它可能会混淆与您一起工作的其他人,请考虑:
<?php
$array = array('huh' => 'var_dump', 'whatThe' => 'It\'s tricky!', 'iDontGetIt' => 'This Extract Function');
extract($array);
$huh($whatThe, $iDontGetIt);
?>
Yields:
产量:
string(12) "It's tricky!"
string(21) "This Extract Function"
Would be useful to use in an obfuscation. But I can't get over the "Where did that var come from?" problem that I run into.
在混淆中使用会很有用。但我无法克服“那个 var 来自哪里?” 我遇到的问题。
回答by stephenminded
People get all up-in-arms about extract because it has the potentialto be misused. Doing something like extract($_POST) is not a good idea in any case, even if you know what you are doing. However, it does have it's uses when you are doing things like exposing variables to a view template or something similar. Basically, only use it when you are very certain that you have a good reason for doing so, and understand how to use the extract type parameter if you get the idea of passing something crazy like $_POST to it.
人们对提取物持反对态度,因为它有可能被滥用。在任何情况下,执行诸如 extract($_POST) 之类的操作都不是一个好主意,即使您知道自己在做什么。但是,当您执行诸如将变量暴露给视图模板或类似的事情时,它确实有它的用途。基本上,只有在您非常确定这样做的充分理由时才使用它,并且如果您想将诸如 $_POST 之类的疯狂内容传递给它,并且了解如何使用提取类型参数。
回答by karim79
I guess the reason a lot of people don't recommend using it is that extracting $_GETand $_POST(even $_REQUEST) superglobals registers variables in the global namespace with the same name as each key within those arrays, which is basically emulating REGISTER_GLOBALS = 1.
我想很多人不推荐使用它的原因是提取$_GET和$_POST(甚至$_REQUEST)超全局变量在全局命名空间中注册变量与这些数组中的每个键同名,这基本上是模拟 REGISTER_GLOBALS = 1。
回答by OIS
If you extract in a function, the variables will only be available in that scope. This is often used in views. Simple example:
如果您在函数中提取,则变量将仅在该范围内可用。这在视图中经常使用。简单的例子:
//View.php
class View {
function render($filename = null) {
if ($filename !== null) {
$this->filename = $filename;
}
unset($filename);
extract($this->variables);
ob_start();
$this->returned = include($this->dir . $this->filename);
return ob_get_clean();
}
}
//test.php
$view = new View;
$view->filename = 'test.phtml';
$view->dir = './';
$view->variables = array('test' => 'tset');
echo $view->render('test.phtml');
var_dump($view->returned);
//test.phtml
<p><?php echo $test; ?></p>
With some alternative directories, checks to see if the file exists and defined variables and methods - you've pretty much replicated Zend_View.
使用一些替代目录,检查文件是否存在并定义变量和方法——您几乎复制了 Zend_View。
You can also add $this->outVariables = get_defined_vars();after the include to run code with specific variabels and get the result of these for use with old php code.
您还可以添加$this->outVariables = get_defined_vars(); 在包含运行具有特定变量的代码并获取这些结果以用于旧的 php 代码之后。
回答by Powerlord
I'll let the PHP manualdo the talking for me.
我会让PHP 手册为我说话。
Background: extract($_REQUEST)is the same as setting register_globals = Onin php.ini
背景:extract($_REQUEST)与register_globals = Onphp.ini中的设置相同
回答by James Socol
Never extract($_GET) in a global scope. Other than that, it has its uses, like calling a function that could (potentially) have lots of optional arguments.
永远不要在全局范围内提取($_GET)。除此之外,它还有它的用途,比如调用一个可以(可能)有很多可选参数的函数。
This should look vaguely familiar to WordPress developers:
这对于 WordPress 开发人员来说应该有点熟悉:
function widget (Array $args = NULL)
{
extract($args);
if($before_widget) echo $before_widget;
// do the widget stuff
if($after_widget) echo $after_widget;
}
widget(array(
'before_widget' => '<div class="widget">',
'after_widget' => '</div>'
));

