PHP 中关联数组的默认值,如果键不存在
Default value for an associative array in PHP, if key not present
注意:我已经阅读了Function to set default value of associative array if the key is not present and Default values for Associative array in 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'.
我认为使用尚未定义的键实现类似词法简单性的唯一方法是使用 class 并使用 $a
return 您选择的默认值一个魔法getter。不同键的默认值不同,甚至。
那你就可以写了,
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'
确实 存储值,实际上不仅访问不存在的索引,而且 甚至访问不存在的 属性 (否则会在其他 classes 中工作)现在触发索引通知:
$b = $a->baz;
PHP Notice: Undefined index: baz in ./test.php ...
因此,ArrayObject
实际上 比 StdClass 更差。
这 可能 意味着 ArrayObject 中有一些神奇的优点 可以 访问和利用,但我不知道确定这是怎么回事,如果这是真的,或者可能的话。
您必须使用默认值预填充数组或创建一个对象 class 来处理默认响应。
$array = array('foo' => '123') + array('foo' => '', 'bar' => '');
var_dump( $array );
array(2) {
["foo"]=>string(3) "123"
["bar"]=> string(0) ""
}
您可以在带有键的变量前使用此方法@:
echo @$a['bar'];
我想提交另一个使用数组 ArrayObject
的解决方案,如上所述
这扩展了 class 并略微调整了 offsetGet
行为以始终 return 一个空字符串
这里的parent::
语句调用了扩展class
的函数
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' );
1 步 - 添加此功能:
function getIfIsset(array $array, string $key)
{
return $array[$key] ?? '';
}
2 步 - 使用这个:
echo getIfIsset($mayArray, 'bar');
注意:我已经阅读了Function to set default value of associative array if the key is not present and Default values for Associative array in 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'.
我认为使用尚未定义的键实现类似词法简单性的唯一方法是使用 class 并使用 $a
return 您选择的默认值一个魔法getter。不同键的默认值不同,甚至。
那你就可以写了,
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'
确实 存储值,实际上不仅访问不存在的索引,而且 甚至访问不存在的 属性 (否则会在其他 classes 中工作)现在触发索引通知:
$b = $a->baz;
PHP Notice: Undefined index: baz in ./test.php ...
因此,ArrayObject
实际上 比 StdClass 更差。
这 可能 意味着 ArrayObject 中有一些神奇的优点 可以 访问和利用,但我不知道确定这是怎么回事,如果这是真的,或者可能的话。
您必须使用默认值预填充数组或创建一个对象 class 来处理默认响应。
$array = array('foo' => '123') + array('foo' => '', 'bar' => '');
var_dump( $array );
array(2) {
["foo"]=>string(3) "123"
["bar"]=> string(0) ""
}
您可以在带有键的变量前使用此方法@:
echo @$a['bar'];
我想提交另一个使用数组 ArrayObject
的解决方案,如上所述
这扩展了 class 并略微调整了 offsetGet
行为以始终 return 一个空字符串
这里的parent::
语句调用了扩展class
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' );
1 步 - 添加此功能:
function getIfIsset(array $array, string $key)
{
return $array[$key] ?? '';
}
2 步 - 使用这个:
echo getIfIsset($mayArray, 'bar');