Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/251.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有不存在索引的默认值的PHP数组_Php_Arrays_Hash - Fatal编程技术网

具有不存在索引的默认值的PHP数组

具有不存在索引的默认值的PHP数组,php,arrays,hash,Php,Arrays,Hash,我喜欢Ruby的Hash实现,在这里可以用默认值初始化Hash对象。目前,我正在努力用PHP实现一个类似的对象。这是我在这方面的第一次(非工作)尝试 class DefaultArray extends ArrayObject { protected $_defaultValue; public function setDefault($defaultValue) { $this->_defaultValue = $defaultValue; } publi

我喜欢Ruby的Hash实现,在这里可以用默认值初始化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子句。然而,任何数组值都是空的。有其他实现的想法吗

我厌倦了写作

if(!isset($myarr['value']))
    $myarr['value'] = new MyObj();
$myarr['value']->myVal=5;
而不仅仅是写作

$myarr['value']->myVal=5;
您还可以使用uu构造魔术函数:

class DefaultArray extends ArrayObject
{
    public function __construct($value = null){
        if(is_null($value))
        {
            $this->value = 'default';
        } else {
            $this->value = $value;
        }
    }
}
为什么这么复杂

function initVal($value) {
    global $myarr;
    if(!isset($myarr['value']))
        $myarr['value'] = new MyObj();
}
现在您只需拨打:

initVal('bla');
$myarr['bla']->bla = 'bla';
但是我明白了,你的要整洁得多。

试试这个

现在,您只需要使用不同的键,因为读取访问将初始化该数组项:

$da = new DefaultArray();
assert($da['foo'] == null);
$da->setDefault(1);
assert($da['bar'] == 1);

在这种情况下,您可以使用我的微型库,例如:

class DefaultArray extends ArrayObject
{
    public function __construct($value = null){
        $this->value = ValueResolver::resolve($value, 'default'); // returns 'default' if $value is null
    }
}
不要忘记使用namespace
使用LapaLabs\ValueResolver\Resolver\ValueResolver

还可以进行类型转换,例如,如果变量的值应为
整数
,请使用以下方法:

$id = ValueResolver::toInteger('6 apples', 1); // returns 6
$id = ValueResolver::toInteger('There are no apples', 1); // returns 1 (used default value)

查看更多示例

使用ArrayObject类将所有变量和支持方法保留在一个位置。其中,使用全局函数可能会导致将来出现维护问题。当访问不存在的密钥时,
offsetGet
将使用默认值设置该密钥(请参见
offsetSet
)。这意味着下一次它将存在。如果您不希望出现这种行为,并且总是为不存在的键获取当前默认值,请删除
offsetSet
调用。感谢Gumbo的重要澄清,这种行为在我的第一次测试中让我感到困惑,但这是预期的行为。现在问题已经解决了,我将保留错误的测试代码。谢谢,你发现了我的错误!它是$da->setDefault(1),而不是$da->setDefault=1!哦,尴尬!通过此修改,我的示例按预期工作。我还考虑在构造函数中传递默认值,但希望保留ArrayObject的原始构造函数参数。您可以使用我的微型库使其更紧凑。
class DefaultArray extends ArrayObject
{
    public function __construct($value = null){
        $this->value = ValueResolver::resolve($value, 'default'); // returns 'default' if $value is null
    }
}
$id = ValueResolver::toInteger('6 apples', 1); // returns 6
$id = ValueResolver::toInteger('There are no apples', 1); // returns 1 (used default value)