views:

241

answers:

3

Should have asked someone this a long time ago.

What is the best way to use other classes within another class?

For instance, lets say I have an application class:

class Application
{
    public function displayVar() {
        echo 'hello world';
    }
}

and a database class

class Database
{
    // connects to db on construct
    public function query() {
        // queries db
    }
}

now, i want to add a function to my application class that uses a function from the db class

class Application
{
    public function displayVar() {
        echo 'hello world';
    }
    public function getVar() {
        global $db;
        $sql = foo;
        $db->query($sql);
    }
}

so then I have

$db = new Database();
$app = new Application();
$app->getVar('var');

Is there a better way of doing this? Really what I am looking for is the standard way of doing it, not another way of rigging it.

+1  A: 

$db could be a property of your Application class. Any reference to it from within an instance of Application would be done via $this - $this->db

class Application {

  private $db = null;

  public function setDB($name) {
    $this->db = new Database($name);
  }

}
Jonathan Sampson
Yea, I got that but then what about other classes? Like if i had a user.class.php or an admin.class.php, I'd still have to globalize the class to use it.
Citizen
You'll have to give more information about your project.
Jonathan Sampson
+2  A: 

There are a couple of ways of doing that. Global variables is certainly one way and the most looked down upon too. You can create a Singleton and all other classes that need database access would call upon this singleton.

final class Database {
    private static $connection;

    public static function getInstance() {
        if(self::$connection == NULL) {
            self::$connection = // init your database connection
        }
        return self::$connection;
    }
}

And use this database connection object in whatever class needs it.

class Application {
    public function displayVar() {
        echo 'hello world';
    }
    public function getVar() {
        $db = Database::getInstance();
        $sql = foo;
        $db->query($sql);
    }
}

This is all well for a start and a great step beyond using global variables, but you can do better with Dependency Injection. Dependency Injection is a simple concept that if a class has any external dependencies, such as the database connection in your example, you explicitly pass those to the needy class in its constructor or a method. So the new code would look something like Jonathan's solution. A major advantage of using dependency injection is in unit testing, where you can easily replace this actual database object with a mock object and pass it to whoever needs it.

class Application {
    private $db;

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

    public function displayVar() {
        echo 'hello world';
    }

    public function getVar() {
        $sql = foo;
        $this->db->query($sql);
    }
}

For smaller projects, you can easily do it yourself. For large projects, there are various DI frameworks available for PHP

Anurag
Thank you very much!
Citizen
+1  A: 

Include the class file (or set up autoinclude) in each PHP file that needs the class in question. Then instantiate it as needed.

If you need to have a "common" instance of an object, you can look at the Singleton and Factory patterns:

Singleton Pattern Factory Pattern

Peter Loron