tags:

views:

125

answers:

6

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.

A: 

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?

Alexandru Luchian
What's wrong with uppercase variable names?
zombat
Oops...posted that. That was the first thing I checked. By my company's naming convention, we name object instances in title case.
Chad Johnson
+1  A: 

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.

zombat
Oops...posted that. That was the first thing I checked.
Chad Johnson
Hmm... you've got `setSiteId()` there, but not `setUserId()`.
zombat
Crud...I re-updated the post.
Chad Johnson
From your comments above, I'm going with an eAccelerator issue. Try restarting your web server.
zombat
Hmm...I'm not totally convinced it's an eAccelerator cache issue, as I've never, ever experienced an issue that was resolved by restarting the web server or just Apache.
Chad Johnson
A: 
daemonfire300
Yeah...I am distracted today...I re-updated the post. Sorry about that. Believe me, I'd love to use magic methods, but I can't due to non-technical reasons.
Chad Johnson
Why? Couldn't you use them? A wrapper/mapper won't be a "real" mapper if he could not use magic methods^^
daemonfire300
True. My co-worker was just unconvinced for some reason to use them.
Chad Johnson
"Some" strange "reasons" I assume. =) Yes, let him be unconvinced, but setter and getter methods are "THE" important and new things in PHP5+. They improve and expand the OOP in PHP.
daemonfire300
I whole-heartedly agree.
Chad Johnson
daemonfire300: getters and setters break encapsulation (leak implementation details), and go contrary to the basic principle of OOP: classes are supposed to be data members + behavior that uses those data members. as soon as you have `interface Order { public /* Dollar */ function getTotal(); }`, you have code which uses a data member from a different class. maybe `Order` should have `public /* bool */ function display(Display $d);` instead...?
just somebody
@js, I do not agree with you at every point: Because a web application is most of the time a variable "object" with can have various attributes. Like a prism, reflecting different types of light. To represent this "object" we mostly need to use setter and getter. That is what I wanted to say with "improve" and "expand". Actually a wrapper doesn't wrap a object it wraps a request, which I think does not break the main rules of OOP. Tell me if I am wrong =)
daemonfire300
One adversity to using __set and __get would be that code documentation would not reflect the methods available to the data models.
Chad Johnson
+1  A: 

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(), "\n";
    foreach($ro->getMethods() as $rm) {
      echo '  method ', $rm->name, " \n";
    }
    die('----');
  }
  $Log->setUserId($userId);
  $Log->setSiteId($siteId);
  $Log->setLogTypeId($logTypeId);
  $Log->setMessage($message);
  $Log->save();
}
VolkerK
I would totally do that, except I can't test using the release :(
Chad Johnson
A: 

try this

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

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

Grumpy
Your "answer" has absolutely nothing to do with the problem. The problem involves an undefined method, but your answer is trying to address some nonexistent problem with variable names.
Jordan Ryan Moore
+4  A: 

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.

Chris Kloberdanz
HMMMMM....very good deduction. I am going to look into this.
Chad Johnson
Thank you VERY much for your post. That was the problem: PayPal has a 'Log' class. If I could kiss you, well, I still wouldn't, but I'll mark this as the answer.
Chad Johnson
+1 Long shot, but nice work!
zombat
Glad I could help!
Chris Kloberdanz