tags:

views:

79

answers:

2

Hello, I have a problem.

When I create controller, I load model (AccountModel) to class variable "Model" and check if user is logged in:

function __construct()
{
    parent::__construct();

    $this->loadModel("AccountModel", "Model");

    $account = $this->getUserAccount();
    ...
}

Fatal error occurs in getUserAccount():

Fatal error: Call to a member function getAccount() on a non-object in wwwroot/lib/account/account.php on line 57

That's line 57, I call getAccount() on my previously loaded model:

$account = $this->Model->getAccount($_SESSION["account"]["user_account_id"]);

So, looks like $this->Model is not object, but when I put var_dump($this->Model) before calling getAccount(), it says object(AccountModel)#26 (2) ...

I also did var_dump($this), which dumped controller and found that class variable $Model exists and is instance of AccountModel.

Can anybody tell me what the hell is going on?

Btw, model is assigned like that (method of controller):

function loadModel($model_name, $var_name)
{
 // blah blah blah
 $obj = new $class_name();
 $this->$var_name = $obj;
}

Update:

In __construct(), if I directly call getAccount() on my model (previously I called getUserAccount and then getAccount within) without parameter, PHP outputs error sayin:

Missing argument 1 for AccountModel::getAccount()

But when I add parameter it says it's not object again.

Solution:

When loading models, method loadModel() assigned model to instance of controller and stored every name of loaded model into staic property. An error occured when controller has been called second time, so second instance of controller didn't really get its model. Replaced staitc property with object property (checking if model has already been called avoids using require_once lowers overhead, but now will have to find a better solution for that part ;) Anyway, now it works, thanks everyone for helping.

+2  A: 

Have you got warnings and notices disabled? Your loadModel method should be throwing a warning on new $class_name - should be new $model_name :

function loadModel($model_name, $var_name)
{
 // blah blah blah
 $obj = new $model_name();
 $this->$var_name = $obj;
}
Paul Dixon
Ah, my bad, function prepares class name from $model_name (name conversion, etc.), so $obj = new $class_name() is the right one.
usoban
And yes, I have error reporting E_ALL
usoban
OK, in that case I get the feeling you are posting code fragments of where you think the problem lies, possibly omitting the true source of the problem :)
Paul Dixon
Maybe, but since that's all part of my custom framework, it would be hard to post the whole code :)But still, variable IS object, but when I try to execute an it's method it says it isn't ... :(
usoban
+1  A: 

This would be the perfect opportunity to set up a working debugger, e.g. xdebug and netbeans/php

edit: In lack of a "real" debugger (which is way better) a (bad) echo/assert debugger has to do

  • add an error handler method to your class
  • set the error handler within the the constructor
  • set error_reporting=E_ALL and display_errors=On within the constructor
  • set some assert options within the constructor
  • add an assertion within the constructor
  • add two assertions within the getUserAccount() method of your controller

and don't forget to remove the code when you're done debugging

class YourController extends TheController{
  // debug, don't forget to remove/comment out this method
  public static function myErrorHandler($errno, $errstr, $errfile, $errline) {
    $source = file($errfile);
    echo '<fieldset><legend>', htmlspecialchars($errstr. ', '.$errfile.'@'.$errline), "<legend><pre>\n";
    for($i=$errline-8; $i<$errline+3; $i++) {
      if ( isset($source[$i]) ) {
        echo $i+1, ': ', htmlspecialchars($source[$i]);
      }
    }
    echo "\n</pre></fieldset>\n";
    flush();
    return false;
  }

  public function __construct()
  {
    set_error_handler('YourController::myErrorHandler'); // debug, don't forget to remove
    error_reporting(E_ALL); ini_set('display_errors', 1);  // debug, don't forget to remove
    assert_options(ASSERT_ACTIVE, 1);  // debug, don't forget to remove
    assert_options(ASSERT_WARNING, 1);  // debug, don't forget to remove
    assert_options(ASSERT_BAIL, 1);  // debug, don't forget to remove
    assert_options(ASSERT_QUIET_EVAL, 1);  // debug, don't forget to remove
    parent::__construct();

    $this->loadModel("AccountModel", "Model");
    assert( is_object($this->Model) );  // debug, don't forget to remove
    $account = $this->getUserAccount();
  }

  public function loadModel($model_name, $var_name)
  {
     // blah blah blah
     $obj = new $model_name();
     $this->$var_name = $obj;
  }

  public function getUserAccount() {
    assert( is_object($this->Model) );  // debug, don't forget to remove
    assert( is_callable(array($this->Model, 'getAccount')) );  // debug, don't forget to remove
    $account = $this->Model->getAccount($_SESSION["account"]["user_account_id"]);
  }
VolkerK
Will definitely look into xdebug, thank you.
usoban
added some printf-debugger code proposal. Nevertheless look into xdebug. A real debugger beats a printf-have-to-(repeatedly-)change-the-code-debugger any time.
VolkerK
I used xDebug (didn't even know PHPDesigner has it, I thank you for that, will use it next time).Anyway, I solved the problem and your answer helped me quite a bit. Will update my question with the solution (it's was quite a creppy mistake :\)
usoban