Массив PHP со значением по умолчанию для несуществующих индексов
мне нравится хэш-реализация Ruby, где вы можете инициализировать хэш-объект со значением по умолчанию. На данный момент я борюсь с реализацией аналогичного объекта в PHP. Это мой первый (нерабочий) выстрел.
class DefaultArray extends ArrayObject {
protected $_defaultValue;
public function setDefault($defaultValue) {
$this->_defaultValue = $defaultValue;
}
public function offsetExists($index) {
return true;
}
public function offsetGet($index) {
if(!parent::offsetExists($index)) {
if(is_object($this->_defaultValue))
$default = clone $this->_defaultValue;
else
$default = $this->_defaultValue;
parent::offsetSet($index, $default);
}
return parent::offsetGet($index);
}
}
$da = new DefaultArray();
assert($da["dummy"] == null);
$da->setDefault = 1;
assert($da["dummy2"] == 1);
второе утверждение не удастся. Пошаговое выполнение кода показывает, что вызывается offsetGet и выполняется предложение if. Тем не менее, любое значение массива имеет значение null. Есть идеи для альтернативных реализаций?
Я устал пишу
if(!isset($myarr['value']))
$myarr['value'] = new MyObj();
$myarr['value']->myVal=5;
просто писать
$myarr['value']->myVal=5;
4 ответов
$da->setDefault(1);
вы также можете использовать магическую функцию __construct:
class DefaultArray extends ArrayObject
{
public function __construct($value = null){
if(is_null($value))
{
$this->value = 'default';
} else {
$this->value = $value;
}
}
}
попробовать магические методы __get
.
class DefaultArray extends ArrayObject {
protected $_defaultValue;
public function setDefault($defaultValue) {
$this->_defaultValue = $defaultValue;
}
public function __get($index) {
return $this->offsetGet($index);
}
public function offsetGet($index) {
if(!parent::offsetExists($index)) {
if (is_object($this->_defaultValue)) {
$default = clone $this->_defaultValue;
} else {
$default = $this->_defaultValue;
}
parent::offsetSet($index, $default);
}
return parent::offsetGet($index);
}
}
Теперь вам просто нужно использовать разные ключи, так как доступ для чтения инициализирует элементы массива:
$da = new DefaultArray();
assert($da['foo'] == null);
$da->setDefault(1);
assert($da['bar'] == 1);
вы могли бы использовать мою крошечную библиотеку ValueResolver в этом случае, например:
class DefaultArray extends ArrayObject
{
public function __construct($value = null){
$this->value = ValueResolver::resolve($value, 'default'); // returns 'default' if $value is null
}
}
и не забудьте использовать пространство имен use LapaLabs\ValueResolver\Resolver\ValueResolver;
есть также возможность типизации, например, если значение вашей переменной должно быть integer
, Так что используйте этот:
$id = ValueResolver::toInteger('6 apples', 1); // returns 6
$id = ValueResolver::toInteger('There are no apples', 1); // returns 1 (used default value)
Регистрация docs дополнительные примеры
почему так сложно?
function initVal($value) {
global $myarr;
if(!isset($myarr['value']))
$myarr['value'] = new MyObj();
}
теперь вам просто нужно позвонить:
initVal('bla');
$myarr['bla']->bla = 'bla';
но я вижу, ваш гораздо более аккуратный.