PHP:对象在创建后立即为NULL

时间:2010-10-21 16:27:28

标签: php

我们php logs偶尔会出现非常奇怪的错误:Trying to get property of non-object.

这个确切的错误似乎是由以下if语句中对成员$shortName的访问引起的:

class MyLocaleWrapper extends SomeOtherClass {
    …
    protected static $system = NULL;
    public static function getSystemLocale() {
        if (self::$system === NULL) {
            self::$system = new self();
            debug(self::$system);
            self::$system->rfcName = SYSTEM_LOCALE_RFCNAME;
            self::$system->shortName = strtolower(Locale::getRegion(self::$system->rfcName));
            if (self::$system->shortName == '') {
                self::$system->shortName = strtolower(self::$system->rfcName);
            }
            …

# in another file:
class SomeOtherClass {
    …
    public function __construct() {
        # Some documentation about features that have been
        # removed from the constructor, but no real code in here.
        return NULL;
    }
    …

# in yet another file:
MyLocaleWrapper::getSystemLocale();

如果我将self::$system转储到日志文件中,我发现它是NULL - 在使用关键字new构建之后。

最有趣的部分是该文件包含在我们页面的每个请求中,因此每秒执行约10次。但偶尔它会在没有人触摸代码(甚至服务器)的情况下失败。

有没有其他人在PHP中遇到过这样的行为?

6 个答案:

答案 0 :(得分:1)

感谢所有更新。 (见上文关于原始帖子的广泛评论)。

不幸的是,我和你一样难过 - 一切看起来都不错。

要么

  1. 你在php中发现了一些相当模糊的错误,或者......
  2. 这些症状诱使你认为问题出在一个地方,当它实际上是在其他地方时,或者......
  3. 我们所有在该代码中遗漏了一些对于一群经验丰富的php开发人员来说应该是显而易见的。 ; - )
  4. 如果是我的生产系统要处理,我可能会在构造函数中注释掉return NULL,让它在生产中运行一段时间。返回不应该导致任何问题,但这是我在这里看到的唯一奇怪的事情。

    对不起,我无能为力。如果你想出来,请回来告诉我们。

答案 1 :(得分:1)

我们终于发现我们遇到了php bug #50027。将php.ini-variable zend.enable_gc设置为false后,错误就消失了。

答案 2 :(得分:0)

尝试单例方法:

class MyLocaleWrapper {
    …
    private static $system = NULL;//set it to private, and instead of accessing it as $this->system, access it with self::getInstance() or parent::getInstance() if your trying to get the parent instance
    public static function getInstance() {
        if (!(self::$system instanceof self)){
            self::$system = new self();
        }
        return self::$system;
    }
    final private function __construct() { }// Do not allow an explicit call of the constructor: $v = new Singleton();
    final private function __clone() { }// Do not allow the clone operation: $x = clone $v;
    public static function getSystemLocale() {
        $self = self::getInstance();
        log($self);//dump the value into a file with you function
…

看看$ self的价值是什么

您的问题似乎是由覆盖的东西产生的,或者仅仅是因为您没有设置$ system变量

使用单例方法确保实例只设置了一次并且没有任何东西覆盖它。

P.S。该文件实际上做了什么?

答案 3 :(得分:0)

这条线是什么:  self :: $ system-> shortName = strtolower(Locale :: getRegion($ rfcName));? $ rfcName来自哪里? 如果在尝试使用它之前没有定义它,那将导致错误,导致其余代码失败,从而为您提供描述的问题。

由于我没有看到你的全班,我没有回答这个问题的所有信息,所以这只是一个猜测

答案 4 :(得分:0)

这将打印对象一次

class MyLocaleWrapper extends SomeOtherClass {

    protected static $system = NULL;
    public static function getSystemLocale() {
        if (self::$system === NULL) {
            self::$system = new MyLocaleWrapper();

            self::$system->rfcName = 'test';
            self::$system->shortName = strtolower('test');
            if (self::$system->shortName == '') {
                self::$system->shortName = strtolower('test');
            }
                print_r(self::$system);

        }
        return self::$system;
    }
}

# in another file:
class SomeOtherClass {

    public function __construct() {
        # Some documentation about features that have been
        # removed from the constructor, but no real code in here.
        return NULL;
    }
}

# in yet another file:
$l = MyLocaleWrapper::getSystemLocale();
$l = MyLocaleWrapper::getSystemLocale();

答案 5 :(得分:-1)

不确定你是否想出来但我会尝试将新对象直接分配给变量,然后将其分配给self :: $ system。类似下面的代码可能有所帮助。

$newSystem = new self();
$newSystem->rfcName = SYSTEM_LOCALE_RFCNAME;
$newSystem->shortName = strtolower(Locale::getRegion($rfcName));
....
self::$system = $newSystem