We have very strange errors occasionally popping up in our php logs: Trying to get property of non-object.
This exact error seems to be caused by the access to the member $shortName
in the following if statement:
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::$syst开发者_JAVA百科em->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();
if I dump self::$system
into a log file, I see that it is NULL
- right after being constructed with the keyword new
.
The most interesting part is that this file is included in each and every request to our page, so it gets executed ~ 10 times per second. But occasionally it just fails without anyone touching the code (or even the server).
Has anyone else ever experienced such behavior in PHP?
Thanks for all the updates. (see extensive comments above on original post).
Unfortunately, I'm as stumped as you are -- everything looks fine with that code.
Either
- you've found some rather obscure bug in php, or...
- the symptoms are tricking you into thinking the problem is in one place, when it's actually somewhere else, or...
- we're all missing something in that code that should be obvious to a bunch of seasoned php developers. ;-)
If it were my production system to deal with, I'd probably comment out the return NULL
in the constructor, and let it run in production for a while. That return shouldn't cause any problems, but it's the only strange thing I can see here.
Sorry I can't help more than that. Please come back and let us know if you figure it out.
We finally found out we were running into php bug #50027. After setting the php.ini-variable zend.enable_gc
to false, the error vanished.
Try the singleton approach:
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
…
and see what the value of $self is
Your problem seems to spawn from something overwriting or just because your not setting the $system variable
with the singleton approach you ensure that the instance has only been set once and that nothing is overwriting it.
p.s. what does the file actually do?
What is this line: self::$system->shortName = strtolower(Locale::getRegion($rfcName));? Where does the $rfcName come from? If it's not defined before you trying to use it, that would cause an error, causing the rest of the code to fail, giving you the problem you describing.
Since I don't see your entire class, I don't have all the information to answer the question, so this is just a guess
This will print the object once
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();
Not sure if you figured this out but I would try assigning the new object directly to a variable, then assign it to self::$system later on. Something like the code below may help.
$newSystem = new self();
$newSystem->rfcName = SYSTEM_LOCALE_RFCNAME;
$newSystem->shortName = strtolower(Locale::getRegion($rfcName));
....
self::$system = $newSystem
精彩评论