是什么导致这个奇怪的PHP致命错误?

I have a generic Logger class that looks like this:

class Logger {

  ...

  public function add($userId, $siteId, $logTypeId, $message) {
    $Log = LogMapper::create();
    $Log->setUserId($userId);
    $Log->setSiteId($siteId);
    $Log->setLogTypeId($logTypeId);
    $Log->setMessage($message);
    $Log->save();

    ...
  }

  ...

}    

And the Log class:

class Log {

  public function setUserId($userId) {
    if ($this->userId !== $userId) {
      $this->userId = $userId;
    }

    return $this;
  }

  public function getUserId() {
    return $this->userId;
  }

  public function setSiteId($siteId) {
    if ($this->siteId !== $siteId) {
      $this->siteId = $siteId;
    }

    return $this;
  }

  public function getSiteId() {
    return $this->siteId;
  }

  ...

}

As well as the LogMapper class:

class LogMapper extends DataMapper {

  ...

  public static function create($row = false) {
    return new Log($row);
  }

  public static function getById($id) {
    ...
  }

}

As you can see, I have two other classes, LogMapper and Log, which Logger uses to write records to a database.

I also have a mechanism that emails me when a fatal error occurs. I received the following in about a dozen emails:

Call to undefined method Log::setUserId()

My application uses autoloading, and I first thought that may be the problem, but clearly the Logger class is being loaded, and so autoloading has not broken. The path for the Log class is correct in the autoloader...and clearly the Log class has been loaded--otherwise a "Class 'Log' not found" error would have been thrown.

Any ideas what may be causing this error? I do use eAccelerator on the release.

Long shot, but do you have PEAR's Log class installed? This is something I ran across a while back. I tried to make a 'Log' class but it was colliding with PEAR's.

It's hard to say, we can't see the Log class nor the LogMapper. You sure the Log class has setUserId() method? Also why do you name the variable with uppercase? $Log?

Since you didn't post your Log class here, the best guess anyone can probably make is that you forgot to write a setUserId() method in that class.

I can also take a guess that eAccelerator might have your class cached. It's possible you need to restart your web server for changes to take effect, or utilize some other method of clearing the cache.

Just a quick guess:

Use:

public function __set($name,$value)
{
$this->{preg_replace('^set','',$name)} = $value; 
}

This would be a real mapping, I guess.

//Call me stupid, but I still can not find the setUserId() method? //Did you leave it out, while copy&pasting the code? OUTDATED

Maybe reflection can tell you a bit more about the actual class Log used by your code.

public function add($userId, $siteId, $logTypeId, $message) {
  $Log = LogMapper::create();
  if ( !method_exists($Log, 'setUserId') ) {
    $ro = new ReflectionObject($Log);
    echo 'class defined in ', $ro->getFilename(), ' @ ', $ro->getStartLine(), "
";
    foreach($ro->getMethods() as $rm) {
      echo '  method ', $rm->name, " 
";
    }
    die('----');
  }
  $Log->setUserId($userId);
  $Log->setSiteId($siteId);
  $Log->setLogTypeId($logTypeId);
  $Log->setMessage($message);
  $Log->save();
}

try this

if ($this->userId !== $userIdd)

make the var names diffrent, i had such a weird problem one day.