PHP提示:未定义的属性。

8

我遇到了一个奇怪的错误。你可能会说:"为什么奇怪呢?你只是没有这个属性而已。" 不,问题就在于有 这个 属性。

我在这里遇到了一个错误。

// PHP Notice:  Undefined property: stdClass::$roles in
$canWrite = $this->session->isLoggedIn() ? $this->page->canWrite($this->session->user->roles) : false;

这是一个类。
class User {
    protected $roles;

    function getRoles() {
        if (!$this->roles)
        {
            // Get them!
        }

        return $this->roles;
    }
}

当我尝试在这一行访问属性时,就会调用这个方法。一切都运行良好,但我不想增加我的错误日志。发生了什么?

更新1

$this->user->session 是一个 User 对象。

function getUser() {
    if (!$this->user) {
        $u = new User();
                    // Logic
        $this->user = $u;
    }
    return $this->user;
}

User Object
(
    [roleId:protected] => 1
    [roles:protected] => Array
        (
            [root] => Role Object
                (
                    [id:protected] => 1
                    [hrefname:protected] => root
                )

        )
)

更新2

所有属性均通过魔术方法__get()访问。

public function __get($var) {
    if ($this->__isset($var)) {
        $method = 'get'.ucfirst($var);
        if (method_exists($this, $method)) {
            return $this->$method();
        } else {
            return $this->$var;
        }
    }
    throw new Exception("Unrecognized attribute '$name'");
}

UPD3

var_dump($this->session->user)

object(User)#370 (30) {
  ["roles":protected]=>
  array(1) {
    ["root"]=>
    object(Role)#372 (2) {
      ["id":protected]=>
      string(1) "1"
      ["hrefname":protected]=>
      string(4) "root"
    }
  }
}

解释

我在一个地方错误地写成了$this->session->user->id = $user->id,而此时$this->session->user还未被创建。因此,null->id实际上是(new stdClass())->id。好吧,感谢PHP。


2
您的错误信息表明 $this->session->user 不是一个 User 对象。它是一个通用的 stdClass 对象,没有 $roles 属性。请发布设置 $this->session->user 的代码... - Michael Berkowski
2
$this->session->user 是如何创建的?PHP 将其识别为 stdClass对象,而不是 User 对象。 - Cat
1
其次,User::$rolesprotected 的,所以您无法通过 $something->user->roles 公开访问它。这就是 User::getRoles() 方法的作用。 - Michael Berkowski
2
@efpies:安装XDebug,使用兼容的编辑器/IDE,运行到那一行并自己查看内部。在SO上,我们只能对你提供的少量代码进行静态代码分析,就像你有一个要隐藏的秘密一样(以及你非常糟糕、抱怨和没有建设性的描述),没有多余和少于这些。 - hakre
我之前遇到过类似的问题,结果发现是由于 unset 引起的。我误将属性进行了“unset” 而不是清空它们... - Buksy
显示剩余4条评论
2个回答

5
由于错误提示显示未定义的属性在 stdClass 中,这意味着所涉及的对象实际上并不是你认为的 User 类。
这通常意味着对象的创建出现了问题。因此,导致此错误的代码 bug 实际上出现在程序的早期阶段,而不是你提供的代码行。
请查找对象创建的位置。那里很可能是问题所在。
如果没有看到其他代码,我不能提供更多帮助,但希望这可以帮到你。
[编辑]
抛出错误的对象是 $this->session->user(这是你试图访问 ->roles 属性的对象)。
尽管你想说它肯定是一个 User 对象,但事实并非如此。在错误之前立即使用 var_dump($this->session->user),你应该能够看到我的意思。
至于为什么它不是你期望的对象,我仍然无法给出更好的答案。使用像 xDebug 这样的调试器逐行跟踪程序可能会有所帮助。

@efpies - 关于UPD1,你说它是一个“User”对象,但PHP却说它是一个stdClass,导致了错误。在某个地方,你没有访问到你认为的对象。请看我的编辑。 - Spudley
upd3 中,我发布了 var_dump。它显示为一个 User 对象。 - efpies
@efpies - 这是来自于错误行前一行吗?如果是这样,我建议检查 isLoggedIn() 函数;它可能对用户对象执行了意外的操作。也许将三元条件转换成标准的 if else 代码块并在其中添加一个 var_dump - Spudley
不,isLoggedIn() 只是检查 cookies。所以在 isLoggedIn() 之后的 var_dump 打印相同的信息。我现在正在尝试使用调试器... - efpies

2
显而易见的解释是该属性已定义,但受到保护。这意味着它只能被此类及其扩展类访问。
然而,错误信息表明存在其他错误。该类是一个“User”类,但错误表明它是“stdClass”的属性。

所有属性都是通过魔术方法__get()访问的。因此,即使它是protected,也可以使用。当我访问它时,该方法被调用。 - efpies
你在我回答后编辑了你的问题,但是我的答案仍然有效。 - JvdBerg
1
那又怎样?当我在更新问题以获取其他评论时,你已经发布了你的答案。所以我通知了你。有什么问题吗?我的代码中所有属性都是“protected”,但没有其他错误。而且get_class($this->session->user)返回User - efpies

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接