tags:

views:

47

answers:

3

Hey all,

I'm trying to make a small CMS for fun but I'm getting caught up on some semantics with OOP. I have a basic database class and then I have an administrator class. The admin class has to make database queries, so what I've been doing is having the admin class extend the db class and then passing the link to the db resource via construct. My code looks something like this:

class admin extends mysql {
    function __construct($link) {
        $this->link = $link; //$this->link is in the mysql class
    }
}
$db = new mysql($host,$user,$pass,$name);
$admin = new admin($db->link);

I know there should be an easier method to this without extending the db class (which I assume calls an entirely new instance of it). A friend told me to just pass the $db object to the admin class and store it there like so:

class admin {
    var $db;
    function __construct($db) {
        $this->db = $db;
    }
}

$db = new mysql($host,$user,$pass,$name);
$admin = new admin($db);

Is this the correct way to do things? Is there an easier way to reference the db link if it's already been established?

Thanks!

+1  A: 

Yes, your friend is absolutely correct. Well, he's more correct than your original approach.

What you should do is go a step further and create a class whose only job is to query or update to the database and return results. That class is responsible for organizing queries (which are all prepared statements); your "admin" class knows nothing about how to connect to or query the database, only how to use this class, which we'll call "data_layer".

Pass an instance of the data_layer class to the admin class in the constructor, et voilà! You have made a layered program. Congratulations! You're taking your first steps toward a larger world.

Randolpho
A: 

The correct way to do this is by using the singleton design pattern (or registry if you have several connections). Using this design pattern, you do not pass db connections anymore (passing them is bad practice). An example here : http://www.talkphp.com/advanced-php-programming/1304-how-use-singleton-design-pattern.html

greg0ire
You should never singleton DB connections
Randolpho
@Randolpho: why is that?
nico
@Randolpho : of course you do in simple websites, and if you do not, you register them, using the DSN for instance.
greg0ire
@nico One should let the underlying connection pooling mechanism do its job. Singletons prevent that.
Randolpho
@Randolpho: OK, thanks!
nico
I've google around and the Singleton seems pretty much used for this kind of things anyway. This must be because you rarely program multi-threaded scripts in php. Of course, the "singleton" means "one singleton per page" here. I've googled "php connection pooling", and the results show nothing clear on how to achieve this with php... but perhaps the "underlying connection pooling mechanism" is something else than php? If yes what is it and why would a singleton or registry prevent it?
greg0ire
@greg0ire: I can't find a fragment link, but scroll down to the section on persistent connections: http://php.net/manual/en/pdo.connections.php
Randolpho
Interesting, but this connection caching/pooling is reproduced by using the Registry design pattern : http://www.phppatterns.com/docs/design/the_registry (or a singleton if you always use the same DSN). So I don't think using this for a DB connection is a bad practice.
greg0ire
@greg0ire: your Registry design pattern makes the user of the Registry responsible for deciding which connection to use, which is the opposite of what a connection pool does.
Randolpho
+1 I guess the Registry looks a bit like the "reinventing the right wheel" anti-pattern here, there must be a way to keep the Registry's ease of use and the persistent connection (using a getConnection() static method which would instantiate a new object with the option describe in your link I think).
greg0ire
A: 

I'd be inclined to declare and create an instance of the database class inside the admin class. The reason is that operations performed on the database by your admin class may not mix too well with other database access; the admin class might start or commit transactions at moments that are inconvenient for the rest of the application, for instance. That won't happen if the admin class has its own connection.

Brian Hooper