PHP为多维数组添加新索引,无需另行通知


PHP Add New Index to Multidimentional Array Without Notice

举个例子:

$data = array();
$data['a']['one'] = 'test';

这将抛出一个通知,因为$data['a']不存在。因此,我总是这样做:

$data = array();
$data['a'] = array();
$data['a']['one'] = 'test';

或者,如果我在循环中,类似这样的东西:

$data = array();
foreach ($items as $item) {
    if (!isset($data['a'])) {
        $data['a'] = array();
    }
    $data['a']['one'] = $item->getId();
}

这在代码中变得非常具有报告性和混乱。我知道我可以编写某种array_push替代函数来处理这个问题,但我想知道是否有一种方法可以用现有的PHP方法来做到这一点。

首先在某个地方初始化整个数组(所有键、子数组等)是不可行的。

这意味着要记住并维护它——当你有以前没有记录的新数据时,你还必须将它添加到数组初始化中
(Urgh)

我最不愿意将var作为一个数组($data = array();),这样你就不需要is_array()了——在你做任何有用的事情之前(包括右大括号在内的两行代码),这是一行令人讨厌的代码

但是,您不需要进行检查
您的代码检查数组的子数组是否已设置,如果未设置,则将其设置为数组,然后将数据设置到其上。

这是不必要的,因为即使之前没有设置某些子键/数组,也可以在数组中设置数据。

例如,此代码(这是整个文件和运行的所有代码不会抛出错误、警告或通知:

$data['a']['one']['blah']['foo'] = 'test';
print_r($data);
echo $data['a']['one']['blah']['foo'];

上述输出:

Array ([a] => Array ( [one] => Array ( [blah] => Array ( [foo] => test ) ) ) )

test

上述代码不会返回任何警告/通知/错误
还注意到我甚至没有$data = array()
(尽管您希望这样做,因为您可能使用foreach,并且初始化否定了使用is_array的必要性)。

那是error_reporting(-1);

TL;DR;-答案

因此,为了回答您的问题,在您的代码中,您可以这样做(并且不会收到错误/通知/警告):

$data = array();
// more data setting the array up  
foreach ($items as $item) {
    $data['a']['one'] = $item->getId();
}

您可能希望查看ArrayObject类,以下运行时没有错误或警告

<?php
error_reporting(E_ALL| E_NOTICE);
ini_set('display_errors', 1);
$ar = new ArrayObject();
$ar['foo']['bar'] = 1;
assert($ar['foo']['bar'] === 1);

检出视频

在分配期间创建数组:

$data=[];
$data['a'] = ['one' => 'test'];

或者一次性创建整个结构

$data = ['a'=>['one'=>'test']];

我不相信有任何内置方法适合您的需求:PHP数组函数

也许创建自己的函数是实现这一点的最简洁的方法。或者,根据您的用例,您可以创建数据数组,分别添加到密钥a中,如下所示:

$data = array();
$array_data = array();
foreach ($items as $key => $item) {
    $array_data[$key] = $item->getId(); // presuming your 'one' is a dynamic key  
}
$data['a'] = $array_data;

我想,这是否比你的方法更好是一个意见问题。

您可以通过添加@来绕过通知。你也可以禁用我根本不建议使用的通知。

我认为有更好的方法来编写这样的代码:

$a['one'] = 'test';
$a['two'] = 'test';
$data['a'] = $a;

或:

$data['a'] = ['one'=>'test', 'two'=>'test']

或:

$data = ['a'=>['one'=>'test', 'two'=>'test']];

在处理动态数据时,多人建议从一开始就将数组简单地创建为多维数组的方法通常不是一个选项。示例:

$orderItems = array();
foreach ($items as $item) {
    $oId = $order->getId();
    if (!isset($orderItems[$oId])) {
        $orderItems[$oId] = array();
    }
    $pId = $item->getPackageNumber();
    if (!isset($orderItems[$oId][$pId])) {
        $orderItems[$oId][$pId] = array('packages'=>array());
    }
    $orderItems[$oId][$pId][] = $item;
}

听起来我需要创建一个函数来为我做这件事。我创建了这个递归函数,它似乎可以完成任务:

function array_md_push(&$array, $new) {
    foreach ($new as $k => $v) {
        if (!isset($array[$k])) {
            $array[$k] = array();
        }
        if (!is_array($v)) {
            array_push($array[$k], $v);
        } else {
            array_md_push($array[$k], $v);
        }
    }
}
$test = array();
$this->array_md_push($test, array('a' => array('one' => 'test')));
$this->array_md_push($test, array('a' => array('one' => 'test two')));
$this->array_md_push($test, array('a' => array('two' => 'test three')));
$this->array_md_push($test, array('b' => array('one' => 'test four')));

这给了我这个:

array(2) {
  ["a"] => array(2) {
    ["one"] => array(2) {
      [0] => string(4) "test"
      [1] => string(8) "test two"
    }
    ["two"] => array(1) {
      [0] => string(10) "test three"
    }
  }
  ["b"] => array(1) {
    ["one"] => array(1) {
      [0] => string(9) "test four"
    }
  }
}

这很有效。您不需要设置为空数组

$data['a']['one']="测试";