'배열 분리'에 해당되는 글 1건

  1. 2008.10.09 extract

extract

PHP 2008. 10. 9. 14:11
 

extract

(PHP 3>= 3.0.7, PHP 4 , PHP 5)

extract --  배열의 현재 심볼 테이블로 변수들을 입력한다

설명

int extract ( array var_array [, int extract_type [, string prefix]])

이 함수는 배열의 값들을 현재 심볼 테이블에 입력하는데 사용된다. 연관 배열 var_array를 취해서 변수명을 키로, 변수값을 값으로 취급한다. extract_typeprefix 에 따라 각 키/값 쌍에 대해서 현재 심볼 테이블안에 변수를 생성한다.

참고: 버전 4.0.5에 시작하여, 이 함수는 추출된 변수의 수를 반환한다.

참고: EXTR_IF_EXISTSEXTR_PREFIX_IF_EXISTS는 버전 4.2.0에서부터 지원된다.

참고: EXTR_REFS 버전 4.3.0부터 지원된다.

extract()는 각 키가 유효한 변수명을 갖을수 있는지 검사 한다. 또한 심볼 테이블에 존재하는 변수들과의 충돌도 검사한다. 유효하지않은/숫자 키와 충돌인 경우를 취급하는 방법은 extract_type에 의해 결정된다. 다음 값들 중 하나가 될 수 있다:

EXTR_OVERWRITE

충돌이 발생하면, 기존 변수를 덮어쓴다.

EXTR_SKIP

충돌이 발생하면, 기존 변수를 덮어쓰지 않는다. variable.

EXTR_PREFIX_SAME

충돌이 발생하면, prefix를 변수명 앞에 첨가한다.

EXTR_PREFIX_ALL

prefix를 모든 변수명 앞에 첨가한다. PHP 4.0.5에서 시작하여, 이 플래그는 숫자 변수도 적용된다.

EXTR_PREFIX_INVALID

유효하지 않은/숫자 변수명 앞에만 prefix를 첨가한다. 이 플래그는 PHP 4.0.5에서 추가되었다.

EXTR_IF_EXISTS

현재 심볼 테이블에 이미 존재하는 변수만 덮어쓴다. 그렇지 않으면 아무것도 하지 않는다. 이 플래그는 유효한 변수 목록을 정의하고 이 변수들만 추출하는데 유용하다. 예를 들어, 이런 변수는 $_REQUEST에서 정의된 변수들이다. 이 플래그는 PHP 4.2.0에서 추가되었다.

EXTR_PREFIX_IF_EXISTS

현재 심볼 테이블에 앞첨가된 버전의 같은 변수가 존재할때만 앞첨가된 변수명을 생성한다. 이 플래그는 PHP 4.2.0에서 추가되었다.

EXTR_REFS

변수를 참조로써 추출한다. 입력된 변수 값이 var_array 매개변수의 값을 참조한다는 의미를 갖는다. 이 플래그는 그 자체로나 다른 플래그와 OR 연산하여 extract_type에서 사용할수 있다. 이 플래그는 PHP 4.3.0에서 추가되었다.

extract_type가 설정되지 않으면, EXTR_OVERWRITE가 설정되 있다고 가정한다.

prefixextract_typeEXTR_PREFIX_SAME, EXTR_PREFIX_ALL,EXTR_PREFIX_INVALID 또는, EXTR_PREFIX_IF_EXISTS 일때만 요구된다. 앞 첨가된 변수가 유효한 변수명이 아니면, 심볼테이블에 입력되지 않는다.

extract()는 심볼 테이블에 성공적으로 입력된 변수의 수를 반환한다.

extract()가 사용가능한 경우는 wddx_deserialize()에서 반환한 연관배열에 포함되어있는 심볼 테이블 변수들 안에 입력하는것이다.

예 1. extract() 예제코드

<?php

/* Suppose that $var_array is an array returned from
   wddx_deserialize */

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

print
"$color, $size, $shape, $wddx_size\n"
;

?>

위 예제코드는 다음을 출력할것이다:

blue, large, sphere, medium

$size는 덮어씌어지지 않았다, 왜냐하면 EXTR_PREFIX_SAME를 설정했기 때문이다. 결과적으로 $wddx_size가 생성되었다. EXTR_SKIP가 설정되어 있으면, EXTR_OVERWRITE$size가 "medium" 값을 갖게 하고 EXTR_PREFIX_ALL는 새로운 변수인 $wddx_color, $wddx_size, $wddx_shape를 갖게한다.

연관 배열을 사용해야 한다. EXTR_PREFIX_ALLEXTR_PREFIX_INVALID를 사용하지 않으면 숫자로 인덱스된 배열은 결과를 도출할수 없다.

compact() 참고.



add a note add a note User Contributed Notes
extract
Csaba at alum dot mit dot edu
27-Nov-2005 07:41
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.
anon at anon dot org
30-May-2005 07:02
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!
kake26 at gmail dot com
01-May-2005 03:59
The following is a neat use for extract to store and manipulate large amounts of form data from. I basically loop through the $_POST and implode it seperating the key and value pairs by a space. Then store it in a db, the reversing function basically explodes the string to a array. Then converts the indexed array to a associative array then uses extract to seal the deal and make it easily available within a program. My main reason for sharing these are the fact I make some big web applications that store allot of forum data in a DB and these functions make it very easy to quickly and easily store and recall the data. I've contributed it because I spent many hours creating this code and recall going "I wish someone had previously submitted it to the page notes". Would have saved me allot of time and agony and I'm sure I'm not the only person that could really benefit from it, so I decided to share.

<?php
$stack
= array();
foreach (
$_POST as $key => $value
) {
array_push($stack, $key, $value
);
}
// store it
$block = implode(" ",$stack);
// yeilds a space delimited string
// insert query to store string in DB here, like the one below
$query = "INSERT INTO `sometable` VALUES('".$seluser."','".addslashes($block)."');"
;
$result = mysql_query($query) or die("Query failed for block insert: " . mysql_error
());
// note $seluser in my case is a user ID associated with that block
// in one of my web apps
?>

The nice thing is with the above we can quickly create a string of key and value pairs from the data the script-x got. Without really caring what their names are. You know how if register globals are on you say $someformvar rather than $_POST["someformvar"]; , basically the code below reads this previous created block returns it to that state. Sort of like presistant register globals.

<?php
// insert query to grab the previously stored string here
$query = "SELECT * FROM `sometable` WHERE `blockid` = '".addslashes($bid)."';"
;
$result = mysql_query($query) or die("Query failed read: " . mysql_error
());
$sql = mysql_fetch_array($result, MYSQL_ASSOC
);
$array = eplode(" ",$sql["data"
]);
for (
$i = 0; $i < sizeof($array); $i+=2
) {
$myassoc[$array[$i]] = isset($array[$i+1])?$array[$i+1]:NULL
;
}
extract($myassoc, EXTR_OVERWRITE
);
// now you're key and value pairs from $_POST have been restored
// instead of $_POST
?>
pg dot perfection at gmail dot com
14-Mar-2005 10:33
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
);
       }
   }
}
?>
Michael Newton
03-Mar-2005 01:23
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!)
22-Feb-2005 03:31
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';
Aaron Stone
17-Nov-2004 06:44
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.
Adam Monsen <adamm at wazamatta dot com>
03-Oct-2004 12:03
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.

Posted by 철냄비짱
,