...

View Full Version : How to create a global variable of type ?.class.php [PHP5]



Shaitan00
03-25-2009, 04:34 AM
I'm trying to create a global variable ($db) of type Database (as shown below) to be accessed within Tools class.

I'm using PHP5 and running into a little problem... I have 2 files:
- Database.class.php
- Tools.class.php

The contents look as follows:


<?php
require 'Database.class.php';

class Tools
{
public $db = ""; // is this the problem?

function Tools($server, $user, $password, $database)
{
$db = new Database($server, $user, $password, $database);
}

public function Run()
{
$db->Connect();
}
}
?>




<?php
class Database
{
function Database($server, $user, $password, $database)
{
// DO SOMETHING HERE //
}

public function Connect()
{
// DO SOMETHING HERE //
}


For some odd reason this doesn't seem to work ... When I am in Tools.class.php I am trying to access the Database public variable ($db) to run ($db->Connect()) as follows:
$db->Connect();
But ... as you may have guessed ... this doesn't work...

Any clues/hints would be much appreciated.
Thanks,

steelaz
03-25-2009, 04:47 AM
Try this:



<?php
require 'Database.class.php';

class Tools
{
private $db = NULL;

function Tools($server, $user, $password, $database)
{
// Use $this to access class methods and properties
$this->db = new Database($server, $user, $password, $database);
}

public function Run()
{
$this->db->Connect();
}
}
?>


You can also extend database class to use its methods directly



<?php
require 'Database.class.php';

class Tools extends Database
{
private $db = NULL;

function Tools()
{
...
}

function get_data($id)
{
// access Database class method
$this->get_row_by_id($id);
}
}
?>

Shaitan00
03-25-2009, 05:11 AM
steelaz: Sweet, that worked - but I'm having another semi-similar problem...

Now I have an index.php which looks as follows:


<?php
require 'Tools/Tools.class.php';

$tool = new Tools();
$tool->db->Connect();
?>


This doesn't seem to work, I do $tool-> and I get "db" as an option (so far so good) but then -> doesn't give me connect ... In my example seeing as $db is PUBLIC in tools why can't I do $tool->db->Connection(); within index.php?

Thanks a lot...

Fou-Lu
03-25-2009, 05:33 AM
Don't worry about what you can't see. PHP is a datatype weak language and cannot determine the type outside of runtime.
If you're using eclipse for example, you can add this above the $db value:


/**
* @var Database
*/
public $db;

This will let the autocomplete in eclipse (or hopefully whatever you're using) realize that $tools->db is a typeof Database, and can use anything from database.
If you just did $tools->db->connect(); it should still work, you just won't see the autocomplete.
I wouldn't actually let these by public. Its a pain to write an accessor for it, but at least the value cannot be overwritten.

kbluhm
03-25-2009, 05:38 AM
You'll also note (semi-unrelated) that PHP5 constructors are always named __construct() {}.

The naming method you are using still works purely for the sake of compatibility for older code.

Shaitan00
03-25-2009, 05:53 AM
Fou-Lu: Elabortate on "an accessor"? Somethint that would expose all the functionality of $db ...? how would I go about doing that?

Thanks,

Fou-Lu
03-25-2009, 06:10 AM
Accessors / mutators are just methods to handle access to private variables. Generally speaking, they do not reveal the actual underlying variable, but rather perform some processing on it otherwise. In this example, this approach wouldn't be feasible.
This is what I mean:



class Tools
{
private $db;
public function getDB()
{
return $this->db; // This is actually a bad idea, I'll explain here
}
}


Now, the threat you have is that in PHP5 objects are always pass by reference which is different from the PHP 4 implementation where objects were passed by value. So, now you could do this:


$connection = new Database();
$conn2 = new Database2();

$tools = new Tools($connection);
$tmpDB = $tools->getDB();
$tmpDB = $conn2;


Untested. In other languages what should happen is that the value of $db inside of Tools object is now compromised. Even though there is no setter you're returning a pointer to a database which should be overwritable. This is called a privacy leak.

I would probably consider generating this as a design pattern that exposes the database in Tools as a typeof Database. Something like this:


interface IDatabase
{
public function connect(...);
public function select(...);
....
}

class Database implements IDatabase
{
....
}

class Tools implements IDatabase
{
private $db;
public function __construct(IDatabase $db)
{
$this->db = $db;
}

public function connect(...)
{
}
}

$connection = new Database(...);
$tools = new Tools($connection);

$tools->connect(...);

Something like this. This prevents you're leaking problem, but inherits a possible tight coupling problem. This is one of the things you need to really balance out when you're doing OOP to determine what best suits you're needs.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum