2014-10-07 50 views
2

我很好奇,PHP的函数extract如何工作?我想做一个稍微修改的版本。我希望我的功能,使从蛇符号数组的键提取到驼峰时,变量名如:extract()如何在当前作用域中创建变量?

现在提取做到这一点:

$array = ['foo_bar' => 'baz']; 
extract($array); 
// $foo_bar = 'baz'; 

我想的是:

camelExtract($array); 
// $fooBar = 'baz'; 

现在我当然可以骆驼数组第一,但它会很好,如果这可以在一个单一的功能。

编辑:

看来有些人误解了我的问题。是的,我可以这样做:

function camelExtract($array) 
{ 
    $array = ['foo_bar' => 'baz']; 
    $camelCased = []; 
    foreach($array as $key => $val) 
    { 
     $camelCased[camelcase($key)] = $val; 
    } 
    extract($camelCased); 
    // $fooBar = 'baz'; 


    // I can't "return" the extracted variables here 
    // .. now $fooBar is only available in this scope 
} 

camelExtract($array); 
// Not here 

但正如我所说,那么$ foobar的仅仅是范围内可见。

我想我可以做一些事情,如extract(camelCaseArray($array));,这将工作。

+1

所以让自己的函数来做到这一点 – 2014-10-07 19:43:49

+0

是,但我怎么能'神奇地'在当前范围创建变量像那个函数? – Matthijn 2014-10-07 19:44:27

+3

它不是魔术,它的代码 – 2014-10-07 19:44:58

回答

1

extract,并且修改了被调用者局部符号表从内称为功能是魔法。没有办法在不使用plain-PHP的情况下执行相同的操作。

最终的任务可以通过使用John Conde建议的使用extra之后执行到所提供的数组键的转换来解决;虽然我的建议是完全避免类似抽象的行为。然后该方法将类似于

extract(camelcase_keys($arr)); 

其中使得extract从其中导入变量符号表的范围中执行这样的代码包裹在一个功能。


extract行为是不像可变的变量(在调用的函数),是不像使用$ GLOBALS,因为它发生变异被调用者(和被调用者)符号表中看到seen in this demo

function extract_container() { 
    extract(array("foo" => "bar")); 
    return $foo; 
} 

echo "Extract: " . extract_container() . "\n"; // "bar" => 
echo "Current: " . $foo . "\n";     //  => {no $foo in scope} 
echo "Global: " . $GLOBALS['foo'] . "\n";  //  => {no 'foo' in GLOBALS} 

extract C实现可ext/standard/array.c找到。这种行为是允许的,因为本地函数而不是为自己创建一个新的/本地PHP符号表;因此可以(平凡地)修改调用PHP上下文的符号表。

+0

有没有办法:除了其他答案。 – AbraCadaver 2014-10-07 19:55:41

+0

这就是我认为的,在我看来,唯一一个理解这个问题的人会被改变。奇。 – Matthijn 2014-10-07 19:55:58

+0

@AbraCadaver见http://ideone.com/XnaEKi – user2864740 2014-10-07 20:04:40

4

这应该工作: -

function camel(array $arr) 
{ 
    foreach($arr as $a => $b) 
    { 
    $a = lcfirst(str_replace(" ", "", ucwords(str_replace("_", " ", $a)))); 
    $GLOBALS[$a] = $b; 
    } 
} 
+1

这里他们将在当前范围之外可用。但我不认为提取物会将这些物品放在全球范围内。效果会(大部分)相同。但是现在即使称为“骆驼”的方法完成时,这些变量也会“浮现”。 – Matthijn 2014-10-07 20:04:48

+1

如果你希望它是这样的,你可以这样做: - '函数骆驼(数组$ ARR) { 的foreach($改编为$ a => $ B) { $ A = lcfirst(str_replace函数( “”,“”,ucwords(str_replace(“_”,“”,$ a)))); $ {$ a} = $ b; } }' – 2014-10-07 20:16:50

2

可以(谨慎地)使用variable variables

function camelExtract($vals = array()) { 
    foreach ($vals as $key => $v) { 
     $splitVar = explode('_', $key); 
     $first = true; 
     foreach ($splitVar as &$word) { 
      if (!$first) { 
       $word = ucfirst($word); 
      } 
      $first = false; 
     } 
     $key = implode('', $splitVar); 
     global ${$key}; 
     ${$key} = $v; 
    } 
} 

这已经过测试,功能正常。 This condensed answer(在处理小写的第一个单词之后)也很好用,而且更加简洁 - 我的工作只是一步一步地完成骆驼完成工作。

+0

Aa,变量变量似乎是一种可能性。但是,您是否仍然认为这些变量只能在camelExtract的范围内可见?如果你使用提取物,情况并非如此。这在它被调用的范围内创建了新的变量。不是它自己的范围。 – Matthijn 2014-10-07 20:00:44

+1

@Matthijn我做了一个编辑,使用'global'声明来解决这个问题 – sjagr 2014-10-07 20:01:08

+0

这确实可行,但据我所知,提取并不会污染全局范围。但这是一个密切的复制,全球范围的污染是。 – Matthijn 2014-10-07 20:06:12

1
<?php 
    $arr = array('foo_bar'=>'smth'); 
    function camelExtract($arr) { 
     foreach($arr as $k=>$v) { 
      $newName = lcfirst(str_replace(" ","",ucwords(str_replace("_"," ",$k)))); 
      global $$newName; 
      $$newName = $v; 
      //var_dump($newName,$$newName); 
     } 
    } 
    camelExtract($arr); 
    ?> 

或者仅仅是想(T的你有什么建议,更好地模仿原提取物)

$camelArray[lcfirst(str_replace(" ","",ucwords(str_replace("_"," ",$k))))] = $v; 

并提取对得到的camelArray

+0

是的,但这里的新变量只能在camelExtract函数范围中使用。 Extract在调用它的范围内创建这些变量。 – Matthijn 2014-10-07 20:02:42

+1

你说得对。编辑为包含全局$$ newName; – JBar 2014-10-07 20:06:56

相关问题