Мне нравится реализация Hash Ruby, где вы можете инициализировать объект Hash со значением по умолчанию. На данный момент я борюсь с реализацией аналогичного объекта в 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;
$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)
Проверьте документы для получения дополнительных примеров.
Почему так сложно?
function initVal($value) { global $myarr; if(!isset($myarr['value'])) $myarr['value'] = new MyObj(); }
Теперь вам просто нужно позвонить:
initVal('bla'); $myarr['bla']->bla = 'bla';
Но я вижу, что ваш гораздо более аккуратный.