extract() - 从数组中将变量导入到当前的符号表 - php 数组函数
extract()
(PHP 4, PHP 5, PHP 7)
从数组中将变量导入到当前的符号表
说明
extract(array &$array[,int $flags= EXTR_OVERWRITE[,string $prefix=NULL]]): int本函数用来将变量从数组中导入到当前的符号表中。
检查每个键名看是否可以作为一个合法的变量名,同时也检查和符号表中已有的变量名的冲突。
参数
$array一个关联数组。此函数会将键名当作变量名,值作为变量的值。对每个键/值对都会在当前的符号表中建立变量,并受到$flags和$prefix参数的影响。
必须使用关联数组,数字索引的数组将不会产生结果,除非用了EXTR_PREFIX_ALL
或者EXTR_PREFIX_INVALID
。
对待非法/数字和冲突的键名的方法将根据取出标记$flags参数决定。可以是以下值之一:EXTR_OVERWRITE
如果有冲突,覆盖已有的变量。EXTR_SKIP
如果有冲突,不覆盖已有的变量。EXTR_PREFIX_SAME
如果有冲突,在变量名前加上前缀$prefix。EXTR_PREFIX_ALL
给所有变量名加上前缀$prefix。EXTR_PREFIX_INVALID
仅在非法/数字的变量名前加上前缀$prefix。EXTR_IF_EXISTS
仅在当前符号表中已有同名变量时,覆盖它们的值。其它的都不处理。举个例子,以下情况非常有用:定义一些有效变量,然后从$_REQUEST中仅导入这些已定义的变量。EXTR_PREFIX_IF_EXISTS
仅在当前符号表中已有同名变量时,建立附加了前缀的变量名,其它的都不处理。EXTR_REFS
将变量作为引用提取。这有力地表明了导入的变量仍然引用了$array参数的值。可以单独使用这个标志或者在$flags中用 OR 与其它任何标志结合使用。
如果没有指定$flags,则被假定为EXTR_OVERWRITE
。
注意$prefix仅在$flags的值是EXTR_PREFIX_SAME
,EXTR_PREFIX_ALL
,EXTR_PREFIX_INVALID
或EXTR_PREFIX_IF_EXISTS
时需要。如果附加了前缀后的结果不是合法的变量名,将不会导入到符号表中。前缀和数组键名之间会自动加上一个下划线。
返回值
返回成功导入到符号表中的变量数目。
范例
Example #1extract()例子
extract()的一种可能用法是将wddx_deserialize()返回的结合数组中的内容导入到符号表变量中去。
以上例程会输出:
blue, large, sphere, medium
$size没有被覆盖,因为指定了EXTR_PREFIX_SAME
,这使得$wddx_size被建立。如果指定了EXTR_SKIP
,则$wddx_size也不会被建立。EXTR_OVERWRITE
将使$size的值为“medium”,EXTR_PREFIX_ALL
将建立新变量$wddx_color,$wddx_size和$wddx_shape。
注释
Warning不要对不能信任的数据使用extract(),例如用户的输入($_GET,$_FILES,...)。如果这样做,举例说,要临时运行依赖于register_globals的老代码,要确保使用不会覆盖的$extract_type值,例如EXTR_SKIP
,并且要留意应该按照variables_order在php.ini里定义的顺序来提取。
If you still haveregister_globalsand it is turned on, if you useextract()on$_FILESand specifyEXTR_SKIP
, you may be surprised at the results.
This is not recommended practice and is only documented here for completeness. The use ofregister_globalsis deprecated and callingextract()on untrusted data such as$_FILESis, as noted above, a potential security risk. If you encounter this issue, it means that you are using at least two poor coding practices.
You might expect to see something like the following:string(14) "/tmp/phpgCCPX8" array(5) { ["name"]=> string(10) "somefile.txt" ["type"]=> string(24) "application/octet-stream" ["tmp_name"]=> string(14) "/tmp/phpgCCPX8" ["error"]=> int(0) ["size"]=> int(4208) } string(14) "/tmp/phpgCCPX8"However, you would instead see something like this:
string(14) "/tmp/phpgCCPX8" string(14) "/tmp/phpgCCPX8" string(1) "/"
This is due to the fact that sinceregister_globalsis turned on,$testfilealready exists in the global scope whenextract()is called. And sinceEXTR_SKIP
is specified,$testfileis not overwritten with the contents of the$_FILES
array so$testfileremains a string.Becausestrings may be accessed using array syntaxand the non-numeric stringtmp_nameis interpreted as0, PHP sees$testfile['tmp_name']as$testfile[0].
参见
compact()
建立一个数组,包括变量名和它们的值list()
把数组中的值赋给一组变量
[New Version] Example Usage: Example Result: array(3) { ["A"]=> array(4) { ["a"]=> string(36) " CORRECT(including some spaces) " ["b"]=> string(30) "CORRECT(including some spaces)" ["c"]=> string(0) "" ["d"]=> string(0) "" } ["B"]=> array(3) { ["a"]=> string(36) " CORRECT(including some spaces) " ["b"]=> string(0) "" ["c"]=> string(0) "" } ["C"]=> array(3) { ["a"]=> string(30) "CORRECT(including some spaces)" ["b"]=> string(0) "" ["c"]=> string(0) "" } }
You can't extract a numeric indexed array(e.g. non-assoc array). result: PHP Notice: Undefined variable: 1 in /Users/Lutashi/t.php on line 7 Notice: Undefined variable: 1 in /Users/Lutashi/t.php on line 7 NULL
I have made some tests to compare the speed of next constructions: Surprisingly for me extract is 20%-80% slower then foreach construction. I don't really understand why, but it's so.
Sometimes you may want to extract only a named subset of the key/value pairs in an array. This keeps things more orderly and could prevent an unrelated variable from getting clobbered from an errant key. For example, $things = 'unsaid'; $REQUEST = array(He=>This, said=>1, my=>is, info=>2, had=>a, very=>3, important=>test, things=>4); $aVarToExtract = array(my, important, info); extract (array_intersect_key ($REQUEST, array_flip($aVarToExtract))); will extract $my = 'is'; $important = 'test'; $info = 2; but will leave certain $things = 'unsaid' Csaba Gabor from Vienna NB. Of course the composite request coming in from a web page is in $_REQUEST.
They say "If the result is not a valid variable name, it is not imported into the symbol table." What they should say is that if _any_ of the results have invalid names, _none_ of the variables get extracted. Under 4.3.10 on Windows 2000, I was pulling some mySQL records, but needed to convert two fields into IP addresses: I had forgotten the second AS modifier in the SQL query. Because it couldn't extract a variable called INET_NTOA(baz) into the symbol table, it didn't do either of them. (BTW I don't normally stack functions up like that! Just to make a short example!)
[New Version] This function is very useful for filtering complicated array structure. Also, Some integer bitmasks and invalid UTF-8 sequence detection are available. Code:
When extracting from a row after a database query using for example: $row = mysql_fetch_array($result, MYSQL_ASSOC) extract($row); I find that the resultant variables may not match the variable type in the database. In particular I have found integers in the database may gettype() to string on the extracted variable.
Following up on ktwombley at gmail dot com's post: Presumably one easy way of dealing with this security issue is to use the EXTR_IF_EXISTS flag and make sure a) your define acceptable input variables beforehand (i.e. as empty variables) b) Sanitise any user input to avoid unacceptable variable content. If you do these two things, then I'm not sure I see the difference between extract($_REQUEST,EXTR_IF_EXISTS); and assigning each of the variables by hand. I'm not talking here about the idea of storing the variables in a database, just the immediately necessary steps to allow you to use extract on REQUEST arrays with relative safety.
It's really easy to open gaping security holes using extract() on $_REQUEST, $_GET, etc. You have to be really sure of what you're doing, and use the proper flags on extract() to avoid clobbering important variables. For instance, the submission by kake26 at gmail dot com will not only perfectly emulate register globals (that's bad), but it'll store it in a database and recall the same variables every time the script runs (essentially allowing an attacker to attack your script every time it runs via one attack). Oops! To fix it, you'd have to get creative with flags. Maybe you could use EXTR_PREFIX_ALL instead of EXTR_OVERWRITE, for example. Of course, you should also sanitize the form elements to ensure there's no php code in them, and also to make sure any very important variables aren't in the form data. (like the classic $is_admin = true attack)
This function provides exactly the same functionality as extract except that a parameter was added defining the extract target. This function can be used if your PHP installation does not support the required Flags or more important if you would like to extract arrays to another destination as to $GLOBALS, i.e. other arrays or objects. The only difference to extract is that extract_to moves the array pointer of $arr to the end as $arr is passed by reference to support the EXTR_REFS flag.
It is possible to use this as a way to create public attributes for a class.
I use XDebug with NetbeansIDE to for analyzing and developing PHP Code. When debugging an extract statement no new variables appeared in the variable's list. Although all variables created by extract could be examined by explicit watch items and single variables appeared as soon as an PHP script makes use of them I am not sure weather it is a wrong configuration, a feature or a bug in XDebug.
And if you want with PHP 5 an easy way to extract $V by reference, try this : It can be used to create special kind of "free args" functions that let you choose when you call them the way you send variables, and which ones. They are moreover very fast to call thanks to references : Be warned that you can't write : "" because the array can't be referenced by the function, as it's not yet created when the function starts.
If you are working porting an older application, and taking the advice above, extracting only _SERVER, _SESSING, _COOKIE, _POST, _GET, you have forgotten to extract _FILES. Putting _FILES last and using EXTR_SKIP doesn't work because the name of the file upload box is already set as a variable containing only the temporary name of the uploaded file from one of the earlier extracts (I haven't tested to see which one specifically, however). A workaround is to put _FILES last and use EXTR_OVERWRITE. This allows extract to replace that temp-name-only variable with the full array of file upload information.
As shown in the example, if your 'prefix' is used, a single underscore is added to the name of the extracted variable. Meaning, a prefix of 'p' becomes a prefix of 'p_', so 'blarg' prefixed would be 'p_blarg'. If you're not sure what variables you've created through extraction, you can call get_defined_vars() to see all defined variables in the current scope.
Here is a little example of how an extraction method should look like when it needs to work recursive (work on nested_arrays too)... Note that this is only an example, it can be done more easily, and more advanced too.
鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com
图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!