extract

(PHP 4, PHP 5)

extractИмпортирует переменные из массива в текущую таблицу символов

Описание

int extract ( array &$var_array [, int $extract_type = EXTR_OVERWRITE [, string $prefix = NULL ]] )

Импортирует переменные из массива в текущую таблицу символов.

Каждый ключ проверяется на предмет корректного имени переменной. Также проверяются совпадения с существующими переменными в символьной таблице.

Список параметров

var_array

Ассоциативный массив. Эта функция рассматривает ключи массива в качестве имен переменных, а их значения - в качестве значений этих переменных. Для каждой пары ключ/значение будет создана переменная в текущей таблице символов, в соответствии с параметрами extract_type и prefix.

Вы должны использовать ассоциативный массив, использование числовых массивов не приведёт ни к каким результатам, если вы не используете EXTR_PREFIX_ALL или EXTR_PREFIX_INVALID.

extract_type

Параметр extract_type определяет способ трактования неправильных/числовых ключей и коллизий. Он может принимать следующие значения:

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
Извлечь переменные как ссылки. Это означает, что значения таких переменных будут всё ещё ссылаться на значения массива var_array. Вы можете использовать этот флаг отдельно или комбинировать его с другими значениями extract_type с помощью побитового 'или'.

Если extract_type не указан, он трактуется как EXTR_OVERWRITE.

prefix

Обратите внимание, что prefix имеет значение, только если extract_type установлен в EXTR_PREFIX_SAME, EXTR_PREFIX_ALL, EXTR_PREFIX_INVALID или EXTR_PREFIX_IF_EXISTS. Если в результате добавления префикса, не будет получено допустимое имя для переменной, она не будет импортирована в текущую символьную таблицу.

Возвращаемые значения

Возвращает количество переменных, успешно импортированных в текущую таблицу символов.

Список изменений

Версия Описание
4.3.0 Добавлена константа EXTR_REFS.
4.2.0 Добавлены константы EXTR_IF_EXISTS и EXTR_PREFIX_IF_EXISTS.
4.0.5 Эта функция теперь возвращает количество извлеченных переменных. Добавлена константа EXTR_PREFIX_INVALID. Константа EXTR_PREFIX_ALL также включает числовые переменные.

Примеры

Пример #1 Пример использования extract()

Функцию extract() также можно использовать для импорта в текущую таблицу символов переменных, содержащихся в ассоциативном массиве, возвращённом функцией wddx_deserialize().

<?php

/* Предположим, что $var_array - это массив, полученный в результате
   wddx_deserialize */

$size "large";
$var_array = array("color" => "blue",
                   
"size"  => "medium",
                   
"shape" => "sphere");
extract($var_arrayEXTR_PREFIX_SAME"wddx");

echo 
"$color$size$shape$wddx_size\n";

?>

Результат выполнения данного примера:

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.

Примечания

Внимание

Не используйте функцию extract() на непроверенных данных, таких как пользовательский ввод ($_GET, $_FILES и т.п.). Если вы сделаете это, например, для того, что бы временно запустить старый код, использующий register_globals, используйте соответствующий флаг extract_type для того, что бы не перезаписать уже установленные переменные, такой как EXTR_SKIP и удостоверьтесь, что вы извлекаете содержимое в том же порядке, что указан в директиве variables_order в php.ini.

Замечание:

Если у вас включена директива register_globals и вы используете extract() с массивом $_FILES и параметром EXTR_SKIP, вы можете быть удивлены результатами.

Внимание

Это нерекомендуемая практика и документирована здесь только для полноты картины. Использование register_globals считается устаревшим и вызов extract() на непроверенных данных, таких как $_FILES, как уже было сказано выше, потенциальный риск безопасности. Если вы столкнулись с данным случаем, это означает что вы используете как минимум две плохие практики кодирования.

<?php

/* Предположим, что $testfile это имя input загрузки файла
   и что директива register_globals включена. */

var_dump($testfile);
extract($_FILESEXTR_SKIP);
var_dump($testfile);
var_dump($testfile['tmp_name']);

?>
Вы можете ожидать что-нибудь вроде следующего:
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"
Однако, вместо этого вы увидите что-нибудь вроде этого:
string(14) "/tmp/phpgCCPX8"
string(14) "/tmp/phpgCCPX8"
string(1) "/"

Это происходит потому, что так как включена директива register_globals, переменная $testfile уже существует в глобальной области видимости в момент вызова extract(). А так как указан параметр EXTR_SKIP, $testfile не будет перезаписана содержимым массива $_FILES, поэтому $testfile останется строкой. Так как к строкам можно обращаться с помощью синтаксиса массивов и нечисловая строка tmp_name интерпретируется как 0, PHP воспринимает $testfile['tmp_name'] как $testfile[0].

Смотрите также

  • compact() - Создает массив, содержащий названия переменных и их значения
  • list() - Присваивает переменным из списка значения подобно массиву

Коментарии

Автор:
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.
2004-10-02 20:03:25
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
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.
2004-11-17 12:44:41
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
To make this perfectly clear (hopefully), an underscore is always added when the string is prefixed.
extract(array("color" => "blue"),EXTR_PREFIX_ALL,'');// note: prefix is empty
is the same as
$color='_blue';
2005-02-21 21:31:36
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
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:
<?
extract
(mysql_fetch_assoc(mysql_query('SELECT * FROM foo')));
extract(mysql_fetch_assoc(mysql_query('SELECT INET_NTOA(bar) AS bar, INET_NTOA(baz) FROM foo')));
?>

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!)
2005-03-02 19:23:13
http://php5.kiev.ua/manual/ru/function.extract.html
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.

<?php
/**
 * A nested version of the extract () function.
 *
 * @param    array    $array        The array which to extract the variables from
 * @param    int        $type        The type to use to overwrite (follows the same as extract () on PHP 5.0.3
 * @param    string    $prefix        The prefix to be used for a variable when necessary
 */
function extract_nested (&$array$type EXTR_OVERWRITE$prefix '')
{
   
/**
     *  Is the array really an array?
     */
   
if (!is_array ($array))
    {
        return 
trigger_error ('extract_nested (): First argument should be an array'E_USER_WARNING);
    }

   
/**
     *  If the prefix is set, check if the prefix matches an acceptable regex pattern 
     * (the one used for variables)
     */
   
if (!empty ($prefix) && !preg_match ('#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$#'$prefix))
    {
        return 
trigger_error ('extract_nested (): Third argument should start with a letter or an underscore'E_USER_WARNING);
    }

   
/**
     * Check if a prefix is necessary. If so and it is empty return an error.
     */
   
if (($type == EXTR_PREFIX_SAME || $type == EXTR_PREFIX_ALL || $type == EXTR_PREFIX_IF_EXISTS) && empty ($prefix))
    {
        return 
trigger_error ('extract_nested (): Prefix expected to be specified'E_USER_WARNING);
    }

   
/**
     * Make sure the prefix is oke
     */
   
$prefix $prefix '_';

   
/**
     *  Loop thru the array
     */
   
foreach ($array as $key => $val)
    {
       
/**
         *  If the key isn't an array extract it as we need to do
         */
       
if (!is_array ($array[$key]))
        {
            switch (
$type)
            {
                default:
                case 
EXTR_OVERWRITE:
                   
$GLOBALS[$key] = $val;
                break;
                case 
EXTR_SKIP:
                   
$GLOBALS[$key] = isset ($GLOBALS[$key]) ? $GLOBALS[$key] : $val;
                break;
                case 
EXTR_PREFIX_SAME:
                    if (isset (
$GLOBALS[$key]))
                    {
                       
$GLOBALS[$prefix $key] = $val;
                    }
                    else
                    {
                       
$GLOBALS[$key] = $val;
                    }
                break;
                case 
EXTR_PREFIX_ALL:
                   
$GLOBALS[$prefix $key] = $val;
                break;
                case 
EXTR_PREFIX_INVALID:
                    if (!
preg_match ('#^[a-zA-Z_\x7f-\xff]$#'$key{0}))
                    {
                       
$GLOBALS[$prefix $key] = $val;
                    }
                    else
                    {
                       
$GLOBALS[$key] = $val;
                    }
                break;
                case 
EXTR_IF_EXISTS:
                    if (isset (
$GLOBALS[$key]))
                    {
                       
$GLOBALS[$key] = $val;
                    }
                break;
                case 
EXTR_PREFIX_IF_EXISTS:
                    if (isset (
$GLOBALS[$key]))
                    {
                       
$GLOBALS[$prefix $key] = $val;
                    }
                break;
                case 
EXTR_REFS:
                   
$GLOBALS[$key] =& $array[$key];
                break;
            }
        }
       
/**
         *  The key is an array... use the function on that index
         */
       
else
        {
           
extract_nested ($array[$key], $type$prefix);
        }
    }
}
?>
2005-03-14 16:33:43
http://php5.kiev.ua/manual/ru/function.extract.html
A warning about extract() and null values.

This might be an actual Zend2 Engine bug, but it's bad programming practice, so I'm sharing it here instead.

I often work in envrionments where E_STRICT (which would prevent errors like this) isn't on, and I don't have access to change it. I also use a very simple template class that in a nutshell works like this:

$t = new Template('somefile.php');
$t->title = $title;
$t->body = $body;
$t->display();

display() more or less looks like this:

function display(){
    extract(get_object_vars($this),EXTR_REFS);
    ob_start(); include $this->templateFileName;
    return ob_get_clean();
}

If any of the assigned values are null (let's say that in this case $title wasn't initialized above) it causes the engine to do all sorts of incredibly whacky stuff like certifiably lose track of variables in an incredibly inconsistent way. I traced the problem down to the fact that it's using the EXTR_REFS flag. I assume that in PHP's internal variable storage or reference counting mechanism, that trying to extract null references makes it lose track or count of something or rather.

In a nutshell, if you start getting wierd behavior when using extract() make sure that the array or object you are trying to get variables out of doesn't contain null keys or values!
2005-05-30 15:02:01
http://php5.kiev.ua/manual/ru/function.extract.html
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.
2005-11-27 13:41:22
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
Experimentally I found that calling extract() also shows the number of keys if the key is set and is not numeric ! Maybe there was a better definition than mine  . Please have a look to this scripts :

<?PHP 
$var
["i"] = "a";
$var["j"] = "b";
$var["k"] = 1;
echo 
extract($var); // returns 3
?>

<?PHP 
$var2
["i"] = "a";
$var2[2] = "b";
$var2[] = 1;
echo 
extract($var2); // returns 1
?>

(Arash Moslehi)
2006-01-20 15:32:23
http://php5.kiev.ua/manual/ru/function.extract.html
And if you want with PHP 5 an easy way to extract $V by reference, try this :
<?php
   
foreach ($V as $k => &$v) {
        $
$k =& $v;
    }
?>
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 :
<?php
   
function free_args (&$V) {
        foreach (
$V as $k => &$v) {
            $
$k =& $v;
        }
        unset (
$k);  unset ($v);  unset ($V);

       
// be careful that if you need to extract $k, $v or $V variables you should find other names for them in the lines above (ie. $__k, $__v and $__V)
   
}

   
$huge_text '...';

   
$a = array ('arg1' => 'val1''arg2' => &$huge_text); // in this call, only $arg2 will be a true reference in the function
   
free_args ($a);
?>
Be warned that you can't write : "<?php free_args (array ('arg1' => 'val1')); ?>" because the array can't be referenced by the function, as it's not yet created when the function starts.
2006-03-08 06:21:59
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
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.

<?php
   
if( !defined('EXTR_PREFIX_ALL') ) define('EXTR_PREFIX_ALL'3);
    if( !
defined('EXTR_PREFIX_INVALID') ) define('EXTR_PREFIX_INVALID'4);
    if( !
defined('EXTR_IF_EXISTS') ) define('EXTR_IF_EXISTS'5);
    if( !
defined('EXTR_PREFIX_IF_EXISTS') ) define('EXTR_PREFIX_IF_EXISTS'6);
    if( !
defined('EXTR_REFS') ) define('EXTR_REFS'256);
   
   
    function 
extract_to( &$arr, &$to$type=EXTR_OVERWRITE$prefix=false ){
       
        if( !
is_array$arr ) ) return trigger_error("extract_to(): First argument should be an array"E_USER_WARNING );
       
        if( 
is_array$to ) ) $t=0;
        else if( 
is_object$to ) ) $t=1;
        else return 
trigger_error("extract_to(): Second argument should be an array or object"E_USER_WARNING );
       
        if( 
$type==EXTR_PREFIX_SAME || $type==EXTR_PREFIX_ALL || $type==EXTR_PREFIX_INVALID || $type==EXTR_PREFIX_IF_EXISTS )
            if( 
$prefix===false ) return trigger_error("extract_to(): Prefix expected to be specified"E_USER_WARNING ); 
            else 
$prefix .= '_';
       
       
$i=0;
        foreach( 
$arr as $key=>$val ){
           
           
$nkey $key;
           
$isset $t==? isset( $to[$key] ) : isset( $to->$key );
           
            if( ( 
$type==EXTR_SKIP && $isset 
                || ( 
$type==EXTR_IF_EXISTS && !$isset ) )
                    continue;
           
            else if( ( 
$type==EXTR_PREFIX_SAME && $isset )
                || ( 
$type==EXTR_PREFIX_ALL )
                || ( 
$type==EXTR_PREFIX_INVALID && !preg_match'#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$#'$key ) ) )
                   
$nkey $prefix.$key;
                   
            else if( 
$type==EXTR_PREFIX_IF_EXISTS )
                if( 
$isset $nkey $prefix.$key;
                else continue;

            if( !
preg_match'#^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$#'$nkey ) ) continue;
           
            if( 
$t==)
                if( 
$type EXTR_REFS $to->$nkey = &$arr[$key];
                else 
$to->$nkey $val;
            else 
                if( 
$type EXTR_REFS $to[$nkey] = &$arr[$key];
                else 
$to[$nkey] = $val;
           
           
$i++;
        }
       
        return 
$i;
    }
   
   
// e.g.:
   
extract_to$myarray$myobjectEXTR_IF_EXISTS );
?>
2006-03-16 11:24:12
http://php5.kiev.ua/manual/ru/function.extract.html
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)
2006-08-31 13:05:10
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
I would draw your attention to the user note at the very end of this page regarding PREFIXES. The user points out that php adds a '_' to your prefixes.
2007-03-13 02:26:20
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
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.
2007-04-21 15:25:56
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
Dan O'Donnell's suggestion needs a third requirement to work as described:

c) No other variables are defined - especially variables that contain potentially sensitive information.

Without that condition the difference between extract() and assigning variables by hand (and the resulting security implications) should be obvious.

The only valid security step there is (b) - but you should be doing that anyway.
2008-03-13 17:18:00
http://php5.kiev.ua/manual/ru/function.extract.html
Re: anon at anon dot org, about extract() and null values

Personally I've found use extracting multiple resultsets from db where the latter would overwrite the previous when a variable is not null ( and optionally if its not >0 )

It would be useful if $extract_type was extended on top of these two:

EXTR_OVERWRITE
EXTR_SKIP

with something like this:

EXTR_OVERWRITE_NULL 
 - If there is a collision, overwrite the existing variable if it is null 

EXTR_OVERWRITE_0
 - Same thing but == 0 or null

EXTR_SKIP_NULL
 - If there is a collision, skip the new variable if the existing is not null

EXTR_SKIP_0
 - Same thing but == 0 or null

Those ought to cover a few good cases that aren't covered now.
2008-03-16 20:19:36
http://php5.kiev.ua/manual/ru/function.extract.html
When using EXTR_PREFIX_ALL - and probably all the other EXTR_PREFIX_* constants - and a numerically-indexed array, extract() will add an underscore ("_") between the prefix and the index.

<?php

extract
(array('foo''bar'), EXTR_PREFIX_ALL'var');

print_r(get_defined_vars());  // Reveals $var_0 = 'foo' and $var_1 = 'bar'
?>
2009-08-24 07:04:58
http://php5.kiev.ua/manual/ru/function.extract.html
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.
2010-02-23 12:07:41
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
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.
2011-11-01 08:30:51
http://php5.kiev.ua/manual/ru/function.extract.html
You can't extract a numeric indexed array(e.g. non-assoc array).
<?php
$a 
= array(
 
1,
 
2
);
extract($a);
var_dump(${1});
?>

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
2013-04-29 15:55:44
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
It is possible to use this as a way to create public attributes for a class.

<?php
class Foo {

  public function 
__construct ($array) {

     
extract($arrayEXTR_REFS);
      foreach (
$array as $key => $value) {
         
$this->$key = $$key;
         
// Do: $this->key = $key; if $key is not a string.
     
}

  }

}

$array = array(
   
'valueOne'      => 'Test Value 1',
   
'valueTwo'      => 'Test Value 2',
   
'valueThree'    => 'Test Value 3'
);

$foo = new Foo($array);

// Works
echo $foo->valueOne// Test Value 1
echo $foo->valueTwo// Test Value 2

// Does not work!
echo $foo::$valueOne// Fatal error:  Access to undeclared static property: Test::$valueOne
?>
2013-05-13 05:56:25
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
[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:
<?php
/**
 * @param  integer $type    Constant like INPUT_XXX.
 * @param  array   $default Default structure of the specified super global var.
 *                          Following bitmasks are available:
 *  + FILTER_STRUCT_FORCE_ARRAY - Force 1 dimensional array.
 *  + FILTER_STRUCT_TRIM        - Trim by ASCII control chars.
 *  + FILTER_STRUCT_FULL_TRIM   - Trim by ASCII control chars,
 *                                full-width and no-break space.
 * @return array            The value of the filtered super global var.
 */
define('FILTER_STRUCT_FORCE_ARRAY'1);
define('FILTER_STRUCT_TRIM'2);
define('FILTER_STRUCT_FULL_TRIM'4);
function 
filter_struct_utf8($type, array $default) {
    static 
$func __FUNCTION__;
    static 
$trim "[\\x0-\x20\x7f]";
    static 
$ftrim "[\\x0-\x20\x7f\xc2\xa0\xe3\x80\x80]";
    static 
$recursive_static false;
    if (!
$recursive $recursive_static) {
       
$types = array(
           
INPUT_GET => $_GET,
           
INPUT_POST => $_POST,
           
INPUT_COOKIE => $_COOKIE,
           
INPUT_REQUEST => $_REQUEST,
        );
        if (!isset(
$types[(int)$type])) {
            throw new 
LogicException('unknown super global var type');
        }
       
$var $types[(int)$type];
       
$recursive_static true;
    } else {
       
$var $type;
    }
   
$ret = array();
    foreach (
$default as $key => $value) {
        if (
$is_int is_int($value)) {
            if (!(
$value | (
               
FILTER_STRUCT_FORCE_ARRAY |
               
FILTER_STRUCT_FULL_TRIM 
               
FILTER_STRUCT_TRIM
           
))) {
               
$recursive_static false;
                throw new 
LogicException('unknown bitmask');
            }
            if (
$value FILTER_STRUCT_FORCE_ARRAY) {
               
$tmp = array();
                if (isset(
$var[$key])) {
                    foreach ((array)
$var[$key] as $k => $v) {
                        if (!
preg_match('//u'$k)){
                            continue;
                        }
                       
$value &= FILTER_STRUCT_FULL_TRIM FILTER_STRUCT_TRIM;
                       
$tmp += array($k => $value $value '');
                    }
                }
               
$value $tmp;
            }
        }
        if (
$isset = isset($var[$key]) and is_array($value)) {
           
$ret[$key] = $func($var[$key], $value);
        } elseif (!
$isset || is_array($var[$key])) {
           
$ret[$key] = null;
        } elseif (
$is_int && $value FILTER_STRUCT_FULL_TRIM) {
           
$ret[$key] = preg_replace("/\A{$ftrim}++|{$ftrim}++\z/u"''$var[$key]);
        } elseif (
$is_int && $value FILTER_STRUCT_TRIM) {
           
$ret[$key] = preg_replace("/\A{$trim}++|{$trim}++\z/u"''$var[$key]);
        } else {
           
$ret[$key] = preg_replace('//u'''$var[$key]);
        }
        if (
$ret[$key] === null) {
           
$ret[$key] = $is_int '' $value;
        }
    }
    if (!
$recursive) {
       
$recursive_static false;
    }
    return 
$ret;
}
?>
2014-01-10 18:37:25
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
[New Version]

Example Usage:
<?php
$_GET
['A']['a'] = '  CORRECT(including some spaces)    ';
$_GET['A']['b'] = '  CORRECT(including some spaces)    ';
$_GET['A']['c'] = "Invalid UTF-8 sequence: \xe3\xe3\xe3";
$_GET['A']['d']['invalid_structure'] = 'INVALID';

$_GET['B']['a'] = '  CORRECT(including some spaces)    ';
$_GET['B']['b'] = "Invalid UTF-8 sequence: \xe3\xe3\xe3";
$_GET['B']['c']['invalid_structure'] = 'INVALID';
$_GET['B']["Invalid UTF-8 sequence: \xe3\xe3\xe3"] = 'INVALID';

$_GET['C']['a'] = '  CORRECT(including some spaces)    ';
$_GET['C']['b'] = "Invalid UTF-8 sequence: \xe3\xe3\xe3";
$_GET['C']['c']['invalid_structure'] = 'INVALID';
$_GET['C']["Invalid UTF-8 sequence: \xe3\xe3\xe3"] = 'INVALID';

$_GET['unneeded_item'] = 'UNNEEDED';

var_dump(filter_struct_utf8(INPUT_GET, array(
   
'A' => array(
       
'a' => '',
       
'b' => FILTER_STRUCT_TRIM,
       
'c' => '',
       
'd' => '',
    ),
   
'B' => FILTER_STRUCT_FORCE_ARRAY,
   
'C' => FILTER_STRUCT_FORCE_ARRAY FILTER_STRUCT_TRIM,
)));
?>

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) ""
  }
}
2014-01-10 18:38:25
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
I have made some tests to compare the speed of next constructions:
<?php

extract
($ARRAY);

// vs. 

foreach($ARRAY as $key=>$value
    $
$key $value
?>

Surprisingly for me extract is 20%-80% slower then foreach construction. I don't really understand why, but it's so.
2014-09-18 13:18:25
http://php5.kiev.ua/manual/ru/function.extract.html
Автор:
Note that extract() will only create or overwrite variables in the current scope, so
<?
function test(){
 
$a=Array('b'=>1,'c'=>2);
 
extract($a);
}
test();
exit(
"$b");
?>
will produce no output, whereas
<?
function test(){
 global 
$b;
 
$a=Array('b'=>1,'c'=>2);
 
extract($a);
}
test();
exit(
"$b");
?>
will output 1.
2015-01-18 22:35:56
http://php5.kiev.ua/manual/ru/function.extract.html
We can use extract () function for Template Engine:

<?php
#Template.php

class Template
{
    protected 
$viewVars;

    public function 
renderPage($tpl)
    {
       
ob_start();
       
extract($this->viewVarsEXTR_SKIP);
        include 
$tpl;
        return 
ob_end_flush();
    }

    public function 
assign($arr)
    {
        foreach (
$arr as $key => $value) {
           
$this->viewVars[$key] = $value;
        }
        return 
$this;
    }
}

$template = new Template();
$template->assign(
   [ 
'pageHeader' => 'Page Header''content' => 'This is the content page']
);
$template->renderPage('tpl.php');

#tpl.php

<h1><?= $pageHeader?></h1>
<p><?= $content ;?></p>

Output:

Page Header
This is the content page
2018-05-29 06:29:12
http://php5.kiev.ua/manual/ru/function.extract.html
Using extract's return parameter can lead to unintended results, particularly with EXTR_REFS:

<?php

$my_data 
= [
   
'count' => 15,
   
'name' => 'foo',
];

$count extract$my_dataEXTR_REFS );

echo 
$my_data['count']; // 2, not 15.
2018-06-18 09:59:57
http://php5.kiev.ua/manual/ru/function.extract.html
If an object is typecasted into an array and "extracted",only the public properties will be accessible.Methods are of course omitted.
<?php
class Test{
    public 
$name '';

    protected 
$age 10;

    public 
$status 'disabled';

    private 
$isTrue false;

    public function 
__construct()
    {
       
$this->name 'Amolo';
       
$this->status 'active';
    }

    public function 
getName()
    {
        return 
$this->name;
    }

    public function 
getAge()
    {
        return 
$this->age;
    }

    public function 
getStatus()
    {
        return 
$this->status;
    }

}

$obj = (array) new Test();
var_dump($obj);
/* array(4) { ["name"]=> string(5) "Amolo" ["*age"]=> int(10) ["status"]=> string(6) "active" ["TestisTrue"]=> bool(false) } */
extract((array)new Test());
echo 
$name//Amolo
echo  $status//active
echo $age;//Notice: Undefined variable: age
echo $isTrue;//Notice: Undefined variable: isTrue
2018-07-26 20:14:21
http://php5.kiev.ua/manual/ru/function.extract.html
In response to Dan O'Donnell's note:

"Presumably one easy way of dealing with this security issue is to use the EXTR_IF_EXISTS flag and make sure"

Not necessarily - even using the EXTR_IF_EXISTS flag could be extremely dangerous - imagine this code running...

<?php

global $sql ;

function 
runSql ()
{
 
$result $conn->query($sql);
 
$conn-> close();
  return 
$result;
}

function 
extractGet ()
{
 
$name '' ;
 
$address '' ;
  foreach ( 
$_GET as $key => $value )
   
$_GET[$key] = urldecode $value ) ;
 
extract($_GET,EXTR_IF_EXISTS);
 
$sql str_replace '{NAME}'$name$sql ) ;
 
$sql str_replace '{ADDRESS}'$address$sql ) ;
}

function 
outputResult $res )
{
  echo 
'<pre>'.print_r $res->fetch_array(MYSQLI_NUM) ).'</pre>' ;
}

$sql 'SELECT postcode FROM Customers WHERE name={NAME} AND address={ADDRESS}';
extractGet () ;
$res runSql () ;
outputResult $res ) ;
?>

Now can you see a massive security issue here...

seems all well and good if we had a url like 

mycode.php?name=joe%20bloggs&address=20%20Any%20Street

as that would specifically find joe bloggs of 20 any street.

however what if someone typed in

mycode.php?sql=SELECT%20password%20FROM%20Customers

or even worse

mycode.php?sql=DELETE%20from%20Customers

The problem here is that even though as far as you're aware you defined both name and address as the only two empty variables within that function - you may have forgotten about global variables, and these global variables could cause major security issues

In the example above $sql is defined as "SELECT postcode FROM Customers WHERE name={NAME} AND address={ADDRESS}" which seems all well and good, and safe, and then later on str_replace in the extractGet function replaces {NAME} and {ADDRESS} with the name and address variables from $_GET - but if GET contains an SQL variable then that would overwrite the global $sql variable before the str_replace function - and if the str_replace function finds no matches it just returns the original string - in the above two examples the SQL string would be "SELECT password FROM Customers" which in the example outputResult just prints the data retrieved from the database and so in this stage it could print all the customers passwords (hopefully encrypted!) to the screen (oops!) or in the second example the SQL string would be "DELETE from Customers" - with no WHERE clause that would delete all the data from the Customers table and of course a combination of

SELECT table_name FROM information_schema.tables

and

DROP TABLE <table_name>

could be a real disaster!

Of course, this is only a basic example, but it could be quite easy to forget about global variables and these global variables could quite easily be used with extract to cause serious security risks if GET, REQUEST or POST is sent to extract!
2021-04-22 10:38:09
http://php5.kiev.ua/manual/ru/function.extract.html

    Поддержать сайт на родительском проекте КГБ