2

问题

我有一个嵌套的 PHP 数组,我需要从平面标量值中填充它。问题是在收到填充平面标量值的请求之前,我无法提前知道嵌套 PHP 数组的结构是什么。

例子

// example where we populate the array using standard PHP
$person['contact_info']['fname']  = 'Attilla';
$person['contact_info']['lname']  = 'Hun';
$person['contact_info']['middle'] = 'The';    
$person['hobbies'][0]             = 'Looting';
$person['hobbies'][1]             = 'Pillaging';

// example where we populate the array from flat scalar values
// (these are obtained from the user via name-value pairs)

// how can I correctly populate $person from this??
print($_GET['contact_info.fname']);   // 'Smokey';
print($_GET['contact_info.middle']);  // 'The';
print($_GET['contact_info.lname']);   // 'Bear';

// how can I correctly populate $person from this??
print($_GET['contact_info.fname']);   // 'Jabba';
print($_GET['contact_info.middle']);  // 'The';
print($_GET['contact_info.lname']);   // 'Hutt';

// How can I use these three flat scalars 
// to populate the correct slots in the nested array?

问题

我知道我一定不是第一个需要将平面名称-值对转换为嵌套 PHP 数组(或任何编程语言中的嵌套数组)的人。将这些平面标量名称-值对转换为适当的 PHP 嵌套数组的既定方法(如果有)是什么?

只是为了重新迭代,我无法提前知道用于填充数组的名称-值对是什么,这是我在这里处理的一个约束。

更新

我不知道值(或者,如果您愿意,由标量值表示填充的数组键)这一事实是我正在处理的特定问题空间的约束。这不是关于基本 PHP 数组语法的问题。

4

2 回答 2

0

我不确定你说你不能提前知道名称-值对是什么意思。

参考您的示例,这将起作用:

<?php

$person['contact_info']['fname']  = $_GET['contact_info.fname'];
$person['contact_info']['lname']  = $_GET['contact_info.middle'];
$person['contact_info']['middle'] = $_GET['contact_info.lname']);    

?>

事先不知道这些是给定的——这就是用户输入的方式。

您必须提前知道密钥。如果没有此信息,您将无法知道如何将值映射$_GET$person.

如果您事先不知道密钥,则无法解决此问题。如果您事先不知道密钥,则您的软件设计中存在严重缺陷。

于 2010-06-24T22:44:55.353 回答
0

注意:我下面的 PHP 代码是一个 hack,而是这样做。 之前有人发布了一个更好的解决方案,但现在该帖子已经消失了。简而言之,您已经可以将表单中的值数组提交给 PHP:

<form ...>
<input type="text" name="contact_info[fname]">
<input type="text" name="contact_info[lname]">
<input type="text" name="contact_info[middle]">
</form>

name 属性中的方括号完全符合您的想法。提交时,$_POST['contact_info']将是一个包含三个键的数组fnamelname, 和middle

如果可能的话,您应该使用这种方法而不是我在下面编写的代码。它更干净,更好,更易于维护,这是应该的方式。


这是一个有趣的挑战。我们将使用 PHP 的有趣方式来引用我们的优势。鉴于:

  • $input 是一个数组,仅包含用于 $person 的键/值对
  • 句点始终是分隔符
  • 您永远不会遇到同时具有数组和非数组值的键,即永远不会同时存在 'contact_info' 和 'contact_info.foo'

那么这个函数可能是你的起点。

function nifty_splitty_magicky_goodness($input) {
// Start out with an empty array.
    $person = array();
    foreach($input as $k => $v) {
    // This turns 'a.b' into array('a', 'b')
        $key_parts = explode('.', $k);
    // Here's the magic.  PHP references aren't to values, but to
    // the variables that contain the values.  This lets us point at
    // array keys without a problem.  Sometimes this gets in the way...
        $ref = &$person;
        foreach($key_parts as $part) {
        // If we didn't already turn the thing we're refering to into an array, do so.
            if(!is_array($ref))
                $ref = array();
        // If the key doesn't exist in our reference, create it as an empty array
            if(!array_key_exists($part, $ref))
                $ref[$part] = array();
        // Reset the reference to our new array.
            $ref = &$ref[$part];
        }
    // Now that we're pointing deep into the nested array, we can
    // set the inner-most value to what it should be.
        $ref = $v;
    }
    return $person;
}

// Some test data.    
$input = array(
    'a.b' => 1,
    'a.c' => 2,
    'a.d.e' => 3,
    'f' => 4,
    'g.h' => 5
);
// Run it!
var_export(nifty_splitty_magicky_goodness($input));
// Should produce:
array (
  'a' => 
  array (
    'b' => 1,
    'c' => 2,
    'd' => 
    array (
      'e' => 3,
    ),
  ),
  'f' => 4,
  'g' => 
  array (
    'h' => 5,
  ),

同样,这是一个黑客。 您应该使用 PHP 表单处理来为您处理这个问题。

于 2010-06-24T22:56:10.427 回答