Call to a member function on a non-object (PHP 5)

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Call to a member function on a non-object (PHP 5)

Post by Bon Bon »

Basically, if I have the following code:

Code: Select all

class FirstClasss {
    function DoSomething ()  {
        return 1;
    }
}

$x = new FirstClass;
Is there any way of using the $x variable in other classes like so:

Code: Select all

class SecondClass {
  $MyVal = 1;

    function Compare ()  {
        if (strcmp($x->DoSomething(), $this->MyVal) == 0) return TRUE;
    }
}
If not, what is the best way to get something like this to work, I have also tried doing FirstClass::DoSomething() but then I have the problem of $this belonging to SecondClass.

Cheers as this one has got me.
User avatar
onion2k
Jedi Mod
Posts: 5263
Joined: Tue Dec 21, 2004 5:03 pm
Location: usrlab.com

Post by onion2k »

Pass $x to the constructor of the second class?
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Post by Bon Bon »

Cheers for the post, but how do I do that?

Sorry, never really got into OOP before but with PHP 4 going out I thought I better start learning.

Cheers.
User avatar
xpgeek
Forum Contributor
Posts: 146
Joined: Mon May 22, 2006 1:45 am
Location: Kyiv, Ukraine
Contact:

Post by xpgeek »

First example delegate class FirstClass

Code: Select all

class SecondClass {
  $MyVal = 1;
  $x;
//first example delegate class FirstClass
    function SecondClass()
  {
      $this->x = new FirstClasss ();
  }
    function Compare ()  {
        if (strcmp($this->x->DoSomething(), $this->MyVal) == 0) return TRUE;
    }
}
second example - $x is parameter of Compare function

Code: Select all

class SecondClass {
  $MyVal = 1;

    function Compare ($x)  {
        if (strcmp($x->DoSomething(), $this->MyVal) == 0) return TRUE;
    }
}
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Post by Bon Bon »

So what I have in theory is:

Code: Select all

<?php

/* database class file */
class Database {
   function __construct () {
     //db connection
   }

   function Query ($sql) {
     return mysql_query($sql);
   }
}

$database = new Database;

/* session class file */
class Session {
  private $Database;

   function UseDatabaseObject ($Database) {
       $this->Database = $Database;
   }

   function CleanUp () {
     $this->Database->Query("DELETE LOW_PRIORITY FROM `session` WHERE DATE_ADD(`touched`, INTERVAL 2 DAY) < NOW()");
   }
}

$session = new Session;
$session->UseDatabaseObject($database);
$session->CleanUp();

?>
So is this the best way I should be doing this kind of thing, this example is a lot closer to what I am trying to achieve, the only problem is I want to use the __construct to clean sessions etc but it is not possible this way so I have to manually call Session::CleanUp.
User avatar
xpgeek
Forum Contributor
Posts: 146
Joined: Mon May 22, 2006 1:45 am
Location: Kyiv, Ukraine
Contact:

Post by xpgeek »

You can use constructor to create the object and destructor to clean up objects.
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Post by Bon Bon »

Are you saying the best way to do this is through the following:

Code: Select all

<?php

/* database class file */
class Database {
  function __construct () {
    // db connect + select
  }

   function Query ($sql) {
     return mysql_query($sql);
   }
}

$database = new Database;

/* session class file */
class Session {
  private $Database;

  function __construct () {
    $this->Database = new Database;
  }

  function __destruct () {
    $this->Database->Query("DELETE LOW_PRIORITY FROM `session` WHERE DATE_ADD(`touched`, INTERVAL 2 DAY) < NOW()");
  }
}

$session = new Session;

?>
- or -

Code: Select all

<?php

/* database class file */
class Database {
   function Query ($sql) {
     return mysql_query($sql);
   }
}

$database = new Database;

/* session class file */
class Session {
  private $Database;

  function __construct ($Database) {
    $this->Database = $Database;
  }

  function __destruct () {
    $this->Database->Query("DELETE LOW_PRIORITY FROM `session` WHERE DATE_ADD(`touched`, INTERVAL 2 DAY) < NOW()");
  }
}

$session = new Session($database);

?>
Or is there another way, because what I want to do is the second but without having to pass the object when creating an instance of Session but rather have it included in the Session class itself like so:

Code: Select all

<?php

/* database class file */
class Database {
   function Query ($sql) {
     return mysql_query($sql);
   }
}

$database = new Database;

/* session class file */
class Session {
  private $Database;

  function __construct () {
    $this->Database = $database;
  }

  function __destruct () {
    $this->Database->Query("DELETE LOW_PRIORITY FROM `session` WHERE DATE_ADD(`touched`, INTERVAL 2 DAY) < NOW()");
  }
}

$session = new Session;

?>
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Post by Bon Bon »

Put it simple, I do not want to initiate another class when 1 is already initiated because this is wasting resources, nor do I want to pass a variable by reference because this is messy when I will be passing about 5 to 10 at any 1 time, I do not want to extend the database class either because this means that I am duplicating functionality that is already there which I do not want.

I am basically trying to push a variable into the class without using globals, effectively a global without being global, if anyone knows how?
User avatar
olog-hai
Forum Commoner
Posts: 34
Joined: Thu May 31, 2007 8:47 am
Location: Québec city, QC, Canada

Post by olog-hai »

Do your database class a singleton.

Code: Select all

<?php 

/* database class file */ 
class Database { 

  static $instance = null

  function __construct () { 
    // db connect + select 
  } 

   function getInstance(){
       if (self::$instance ===null){
             self::$instance = new Database();
        }
        return self::$instance;
  }

   function Query ($sql) { 
     return mysql_query($sql); 
   } 
} 

$database = new Database; 

/* session class file */ 
class Session { 
  private $Database; 

  function __construct () { 
    $this->Database = Database::getInstance(); 
  } 

  function __destruct () { 
    $this->Database->Query("DELETE LOW_PRIORITY FROM `session` WHERE DATE_ADD(`touched`, INTERVAL 2 DAY) < NOW()"); 
  } 
}
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Post by Bon Bon »

Spot on, I love you.
User avatar
Zoxive
Forum Regular
Posts: 974
Joined: Fri Apr 01, 2005 4:37 pm
Location: Bay City, Michigan

Post by Zoxive »

Modified Function i found on these forms a while ago..

Code: Select all

function &singleton($class,$Params=''){
  static $Objects = array();
  if(!isset($Objects[$class])){
    if(!empty($Param)){
      $Objects[$class] = new $class($Params);
    }else{
      $Objects[$class] = new $class;
    }
  }
  return $Objects[$class];
}

Code: Select all

/**
 *   Example
*/

class class_ext{

  protected $Q = NULL;

  function __construct(){
    $this->Q = &singleton('Mysql'); //Loads Class Mysql
   }
}
User avatar
olog-hai
Forum Commoner
Posts: 34
Joined: Thu May 31, 2007 8:47 am
Location: Québec city, QC, Canada

Post by olog-hai »

The '&' is not necessary in PHP 5 as passing objects 'by reference' is now the default behaviour, which means that creating a 'clone' requires extra effort.
User avatar
Zoxive
Forum Regular
Posts: 974
Joined: Fri Apr 01, 2005 4:37 pm
Location: Bay City, Michigan

Post by Zoxive »

olog-hai wrote:The '&' is not necessary in PHP 5 as passing objects 'by reference' is now the default behaviour, which means that creating a 'clone' requires extra effort.
Doesn't hurt, and its easier on my brain to remember that i want it as a reference.
User avatar
olog-hai
Forum Commoner
Posts: 34
Joined: Thu May 31, 2007 8:47 am
Location: Québec city, QC, Canada

Post by olog-hai »

I like your singleton factory :)
Bon Bon
Forum Commoner
Posts: 66
Joined: Sat Mar 13, 2004 10:21 pm
Location: UK

Post by Bon Bon »

The original solution about the singleton is the what I was looking for and to be honest I feel it is the best solution. If you're wondering, this is what I have got:

database.php

Code: Select all

<?php

class Database {
  static $instance = null;

  function __construct () {
    // db connect + select
  }

  final function GetInstance() {
    if (self::$instance === null) self::$instance = new Database();
    return self::$instance;
  }

  function Query ($sql) {
    // run query etc
  }
}

$database = Database::GetInstance();

?>
session.php

Code: Select all

<?php

class Session {
  private $Database;

  function __construct () {
    $this->Database = Database::GetInstance();
    // do session cleaning
  }

  function __destruct () {
    // log things
  }
}

$session = new Session;

?>
Post Reply