【问题标题】:&__get() issues, again. Major frustration is afoot&__get() 问题,再次。重大挫折正在发生
【发布时间】:2011-06-09 04:08:15
【问题描述】:

好吧,我很沮丧,因为我认为我已经解决了这个问题,或者之前已经成功地完成了。

快速初步:

  • PHP 5.3.6。
  • 错误报告增加到 11。(-1 实际上;未来安全,所有错误/通知

我有一个类,它聚合请求参数。对于咯咯笑,这里有一个精简版:

class My_Request{
    private $_data = array();
    public function __construct(Array $params, Array $session){
        $this->_data['params']  = $params;
        $this->_data['session'] = $session;
    }
    public function &__get($key){
        // arrg!
    }
}

无论如何,arrg! 的原因是,无论我尝试什么,只要$key 不存在,我总是会收到错误消息。我已经尝试过:

// doesn't work
$null = null;
if(isset($this->_data[$key])){ return $this->_data[$key]; }
return $null;

// doesn't work
return $this->_data[$key];

有人告诉我,三元运算符不能产生引用,ergo,这当然不起作用,但我们从if 条件尝试中知道无论如何。例如会发生什么:

// params will have foo => bar, and session hello => world
$myRequest = new My_Request(array('foo' => 'bar'), array('hello' => 'world'));

// throws an error - Undefined index: baz
echo $myRequest->params['baz'];

我在这里疯了;也许我幻想了一个我实现这一目标的场景。是否不可能(不发出通知)成功地做到这一点?


澄清:我尝试过的事情

上述:

// no check, no anything, just try returning : fails
public function &__get($key){
    return $this->_data[$key];
}

// null variable to pass back by reference : fails
public function &__get($key){
    $null = null;
    if(isset($this->_data[$key])){
        return $this->_data[$key];
    }
    return $null;
}

其他尝试:

// can't work - can't return null by reference nor via ternary : fails
public function &__get($key){
    return isset($this->_data[$key])
        ? $this->_data[$key]
        : null;
}

【问题讨论】:

    标签: php reference getter magic-methods


    【解决方案1】:
     echo $myRequest->params['baz'];
    

    __get 函数中的 isset 检查将从 $this->_data 查找 "params" 并返回数组。您收到的通知来自班级外部,并且是关于返回数组中的键 "baz" - 在您的示例中从未实际定义过。

    【讨论】:

    • 谢谢马里奥;很公平,我通过引用返回以支持多维数组,所以.. 百万美元的问题是如何验证嵌套键的存在?我必须迭代嵌套数组,但我没有可用的必要信息,就像与多维数组的每个级别关联的所有键一样。
    • 简单的答案:你不能。 -- 这将需要非常复杂的解决方法,将返回的数组包装到一个 ArrayObject 中(为简单起见,隐式引用),并覆盖那里的访问方法。 (需要递归地应用自身以获取更多数组。)
    • 啊,该死的,另一个要实现的接口,我不想拒绝错误报告,我喜欢它。 __get() 通过引用是功能还是错误?如果这是一项功能,我希望这是事后的想法。
    • 另一种阐述:鉴于我直接使用数组 - 比如public $params = array(); - 在这些情况下我能做什么?是否有任何合理的支持来检查嵌套键的存在?
    • 你需要它做什么?也许你可以为你的 $session 和 $params 数组使用单一级别的解决方法。只需实现 QuietArray extends ArrayObject 并做好。
    【解决方案2】:

    我意识到这个问题已经过时了,但我只是在寻找答案时通过谷歌偶然发现了它(我已经找到了答案)。

    class My_Request{
        private $_data = array();
        public function __construct(Array $params, Array $session){
            $this->_data['params']  = $params;
            $this->_data['session'] = $session;
        }
        public function &__get($key){
            if (array_key_exists($key, $this->_data)) {
                return &$this->_data[$key]; // Note the reference operator
            } else {
                $value = null; // First assign null to a variable
                return $value; // Then return a reference to the variable
            }
        }
    }
    

    $this->_data[$key] 是一个返回值的操作,所以返回值会导致错误,因为它不是引用。要使其返回引用,您必须使用引用:&$this->_data[$key]

    【讨论】:

    • 谢谢@Dagan!从那以后,我改变了我的方法,转而支持一种解析路径遍历,对于$o->get('foo.bar.qux');,它大致(internally)转换为$this->data['foo']['bar']['qux'];。考虑到遍历方法,我可以通过引用返回而不会出现问题。
    【解决方案3】:

    没有尝试过,因为我避免使用 __get__set,但也许这对你有用:

    public function __get($key){
       if(!isset($this->_data[$key]))
           return false;
    
       return $this->_data[$key];    
    }
    

    完全未经测试,但看起来它可以完成这项工作。

    【讨论】:

    • 谢谢stefgosselin;不,通过引用返回 false 是一样的。通过引用返回$false = false 的方式与我的$null = null 尝试相同。
    • 是的。我懂了。我正在阅读returning references 以更好地了解您要做什么,但我承认还不太清楚。有很多好的 cmets 可以更好地了解如何处理返回的引用,但我从未使用过返回的引用,所以我仍然必须让它浸泡一下。祝你好运朋友;)
    猜你喜欢
    • 2017-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    相关资源
    最近更新 更多