Jump to content

[SOLVED] Call to a member function on a non-object , but why?


xtopolis

Recommended Posts

[i am new to OOP]

 

I have a Singleton? database object that's instantiated at the top of the page, and passed to User($db) on instantiation...  and it gives me that error that I can't call the query() method because it's not an object?  Maybe im passing it wrong..

 

(a form passes post vars to login.php), assume the classes are called, and the defines are there

Login.php

<?php
  require_once 'mysql.php';
  $db = &new MYSQL('xxxx','xxxx','xxxx','xxxx');
// I tested that the $db object is correct by doing a $db->query(Select...); successfully

$client = new Client('alpha',SECRET,DOCROOT);
?>

 

User.php -- only have relevant methods

<?php
class User {
  protected $session;//session instance
  protected $db;
  
  function __construct(&$db)
  {
    $this->db = &$db;
    $this->session = &new Session();
  }
  
  //checks if a session is already logged in, or a new
  //one is being processed
  protected function login()
  {
    //login hash already set?
    if($this->session->get('login_hash')){
      $this->confirmAuth();
    }
    //post set?
    if(empty($_POST['un']) || empty($_POST['pw'])){
      $this->session->set('login_error','You must enter a username and password.');
      $this->redirect();
      die('You are being redirected.');
    }

    $this->processLogin();
  }//login


  //set un/pw vars, check if username exists
  private function processLogin()
  {
    $un = preg_replace('/[^0-9A-Z_]/i','',$_POST['un']);//only allows A-Z,0-9,_ to be input, strips out anything else
    //$pw = hash('whirlpool',$_POST['pw']);
    $pw = $_POST['pw'];
    
    $sql = "SELECT * FROM ".$this->table." WHERE ".UN."='$un'";
      try {
        if(!$result = $db->query($sql)){ // ## HERE IS THE FIRST FAILED CALL #############
          throw new DBException('Error while trying to login.  Please try again');
        }

        //check only 1 hit
        if(mysql_num_rows($result) != 1){
          $this->session->set('login_error','Invalid username or password.');//USERNAME DOES NOT EXIST
          $this->redirect();
          die('You are being redirected.');
        }
        $row = mysql_fetch_array($result);
          $this->checkEnabled($row);

      }catch (DBException $e){//Database problem
        $this->session->set('login_error',$e->getMessage());
        $this->redirect();
        die('You are being redirected.');
      }
  }//processLogin
}//class
?>

 

Client.php

<?php
class Client extends User {
  protected $table;
  protected $secret;
  public $redirect;

  function __construct($table,$secret,$redirect)
  {
    parent::__construct($db);

    $this->table = $table;
    $this->secret = $secret;
    $this->redirect = $redirect;
    
    //handle fails
    if($this->session->get('fails')){
      $this->fails = $this->session->get('fails');
    }else{
      $this->fails = 0;
      $this->session->set('fails',0);
    }
    
    parent::login();
  }//__construct
}
?>

Link to comment
Share on other sites

I kind of grasp what you mean, but I'm confused...  since I declared $db and instantiated it outside all of the classes, shouldn't it be available almost globally?

 

And which scope is it not in?  Client's(and therefore neither User's), or just not in User's scope?

 

 

I tried adding:

$client = new Client($db,'alpha',SECRET,DOCROOT);


function __construct($db,$table,$secret,$redirect)
  {
    $this->db = &$db;
    parent::__construct($this->db);

 

but got the same error.

 

 

~~ oh, can User not see the $db because it technically never gets down to there...?

Link to comment
Share on other sites

mysql.php, this I copied from one of my Sitepoint books, and added one method

 

<?php
//MYSQL

class MYSQL {

  var $host;
  var $user;
  var $pass;
  var $dbname;
  
  var $dbConn;

  //constructor
  function MYSQL($host,$user,$pass,$dbname)
  {
    //assign vars to local vars
    $this->host = $host;
    $this->user = $user;
    $this->pass = $pass;
    $this->dbname = $dbname;
    //connect to DB
    $this->Connect();
  }
  
  //Connect to DB
  function Connect()
  {
    //connect
    if(!$this->dbConn = @mysql_connect($this->host, $this->user, $this->pass)) {
      trigger_error("Could not connect to database.");
    }
    //select db
    if (!@mysql_select_db($this->dbname)) {
      trigger_error("Could not select database.");
    }
  }
  
  function &query($sql)
  {
    if (!$queryResource = mysql_query($sql, $this->dbConn)) {
      trigger_error("Query Failed.");// . mysql_error($this->dbConn));
    }
      return $queryResource;
  }
  
function checkExistsOne($sql)
{
	if (!$queryResource = mysql_query($sql, $this->dbConn)) {
		trigger_error("Query Failed.");// . mysql_error($this->dbConn));
	}
	$howmany = mysql_num_rows($queryResource);

		return $howmany;
}

}//mysql class
?>

Link to comment
Share on other sites

<?php

A

function blah() {
    B
}


class Bleh {

    function f1() {
        C
    }

    function f2() {
        D
    }

}

 

 

Variables from A, B, C and D cannot be accessed from other scopes without being passed or pulled in (for lack of a better term -- pretty much a globalization).

 

 

So, if a variable lives in A, if you don't pass it to or declare it global (well not declare it, but more of use the global syntax) in B, it does not exist in B.

 

 

Similarly, the variable $db does not exist in Client::__construct() unless it is passed or made global to Client::__construct.

 

 

Think of it this way:

 


function f1($blah) {
    echo $blah;
}

function f2($bleh) {
    f1($blah);
    f3($bleh); //example
}

 

Would you expect $blah to be set?  Of course not.

 

Link to comment
Share on other sites

Thank you corbin.

 

I 'fixed' it by adding $db to Client($db,'alpha'....) on instantiation, and then passing $this->db from Client to User::_construct($this->db)..

And then made User's $db it's on ($this->db), and the same in the code calling ($this->db->query())... and now it works.

 

I don't really understand why it needs to be $this->db... but I'm happy that it works.  Thanks again...

 

 

What I changed, for reference:

class Client {
  function __construct($db,$table,$secret,$redirect)
  {
    $this->db = &$db;
    parent::__construct($this->db)
  }
}
//-----------------------
class User {
  function __construct($db)
  {
    $this->db = $db;
  }
...
  function login()
  {
    ...
    $result = $this->db->query($sql);
  }

$client = new Client($db,'alpha'.....)

Link to comment
Share on other sites

class Client {

  function __construct($db,$table,$secret,$redirect)

  {

    $this->db = &$db;

    parent::__construct($this->db)

  }

}

 

 

Did you mean right there?

 

It doesn't need to be stored in this->db first.

 

parent::__construct($db) would work fine.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.