如果键不存在,PHP中关联数组的默认值



注意:我已经阅读了Function,以设置关联数组的默认值(如果键不存在(和PHP中关联数组的缺省值。

比方说:

$a = array('foo' => '123');
$b = $a['bar'];       // PHP Notice:  Undefined index: bar

如果键不存在,我希望默认情况下有一个空字符串"",而不是PHP通知。

我知道解决方案是:

$b = isset($a['bar']) ? $a['bar'] : "";
// or, since PHP 5.3:
$b = $a['bar'] ?: "";      // but this still produces a "PHP Notice"!

有没有办法避开?: "",直接拥有:

$b = $a['bar'];

在没有通知的情况下获得""


注意:这存在于带有的Python中

import collections
d = collections.defaultdict(str)
print(d['bar'])   # empty string, no error

(TL;DR最后一行的答案是"是的,这是可能的-请参阅Scuzzy的答案"(

没有。PHP数组不是这样工作的。

如果您需要已知密钥的默认值,则可以分配它们:

$defaults = [
'foo'  => 'foo',
'bar'  => 'bar',
];
$a = [ 'bar' => 'baz' ];
$a = array_merge($defaults, $a);

现在$a['bar]将是"baz"(不是默认的"bar"(,但$a['foo']将产生"foo"。

我认为,用尚未定义的键实现类似的词汇简单性的唯一方法是使用一个类,并让$a使用magicgetter返回您选择的默认值。不同关键点的默认值也不同。

然后你可以写,

class FakeArray {
private array $values;
private array $defaults;
private $default = null;
public function __get($key) {
if (array_key_exists($key, $this->values)) {
return $this->values[$key];
}
if (array_key_exists($key, $this->defaults)) {
return $this->defaults[$key];
}
return $this->default;
}
public function __construct(array $values = [ ]) {
$this->values = $values;
}
public function setDefault($default) {
$this->default = $default;
}
public function setDefaults(array $default = []) {
$this->defaults = $defaults;
}
};

$a = new FakeArray([ 'foo' => '123' ]);
$a->setDefaults([ 'joe' => 'jim' ]);
$a->setDefault('baz');
$c = $a->foo; // $c is now '123'.
$b = $a->bar; // $b is now 'baz' (no error).
$d = $a->joe; // $d is now 'jim' (not 'baz').

我本以为扩展ArrayObject会非常接近您想要的,允许用$a->key替换$a['key'],但事实并非如此:

class FakeArray extends ArrayObject {
...
public function __get($key) {
return $this->default;
}
}

但是,虽然$a['foo'] = 'bar'确实存储了值,但实际上不仅访问了不存在的索引,而且甚至访问了一个不存在的属性(否则在其他类中会起作用(现在会触发索引通知

$b = $a->baz;
PHP Notice:  Undefined index: baz in ./test.php ...

因此,ArrayObject实际上表现得比StdClass差。

可能意味着ArrayObject中有一些神奇的优点,可以访问和利用,但我不确定这是如何发生的,是否是真的,或者是可能的。

1步-添加此函数:

function getIfIsset(array $array, string $key)
{
return $array[$key] ?? '';
}

2步-使用这个:

echo getIfIsset($mayArray, 'bar');

我想提交另一个使用数组ArrayObject的解决方案,如上所述

这扩展了类,并稍微调整了offsetGet行为,使其始终返回空字符串

这里的parent::语句调用扩展类的函数

class MyArrayObject extends ArrayObject
{
function offsetGet( $key )
{
return parent::offsetExists( $key ) ? parent::offsetGet( $key ) : '';
}
}
$myArray = new MyArrayObject( array( 'foo' => '123') );
var_dump( $myArray['foo'] ); // '123' provided string
var_dump( $myArray['bar'] ); // '' our new default
var_dump( isset( $myArray['foo'] ) ); // true
var_dump( isset( $myArray['bar'] ) ); // false
foreach( $myArray as $key )
{
var_dump( $key ); // only one iteration of '123'
}
var_dump( is_array( $myArray ) ); // false unfortunately
var_dump( is_iterable( $myArray ) ); // true however
var_dump( array_merge( array(), $myArray ) ); // will fail
var_dump( array_merge( array(), (array) $myArray ) ); // will work

最后是

$myArray['bar'] = '456'; // now if we set bar
var_dump( $myArray['bar'] ); // '456' new value
var_dump( isset( $myArray['bar'] ) ); // now true

@miken32建议设置默认值

class MyArrayObject extends ArrayObject
{
protected $default;
public function __construct($array = [], $default = null, $flags = 0, $iteratorClass = "ArrayIterator")
{
parent::__construct( $array, $flags, $iteratorClass );
$this->default = $default;
}
function offsetGet( $key )
{
return parent::offsetExists( $key ) ? parent::offsetGet( $key ) : $this->default;
}
}

您可以通过设置默认值

$myArray = new MyArrayObject( array( 'foo' => '123'), 'mydefault' );

您必须用默认值预先填充数组,或者按照说明创建一个对象类来处理默认响应。

$array = array('foo' => '123') + array('foo' => '', 'bar' => '');
var_dump( $array );
array(2) {
["foo"]=>string(3) "123"
["bar"]=> string(0) ""
}

您可以在带有关键字的变量之前使用此方法@

echo @$a['bar'];

最新更新