Re: DB_Light
| From: | Stig S. Bakken | Date: | Wed, 05 Dec 2001 02:48:07 +0000 |
| Subject: | Re: DB_Light | ||
| References: | 1 | Groups: | php.pear.dev |
| Request: | Send a blank email to pear-dev+get-3400@lists.php.net to get a copy of this message | ||
Martin Jansen wrote:
>
> On Tue, 4 Dec 2001 20:28:37 +0100, Lukas Smith wrote:
>
> >I just would prefer not to force the user to make this decision but to
> >load this added functionality dynamically so the user only loads the
> >code he actually uses.
>
> Yeah. If there is way to load parts of PEAR DB only when they are
> needed, we should go this way.
>
> I don't think that it is basically a good idea to use two differents
> classes (light and heavy), that can be used for the same purpose:
> IMO lot's of people will then wonder, whether they need the light
> or the heavy-weight class for their project.
I just started thinking about this, and came to think of a way we can do
lightweight objects, automatically loading more advanced features the
moment you use them. The payoff is a slightly higher per-call cost.
Here's the idea:
Define a DB_Connection class which is basically something like this:
<?php
class DB_Connection
{
var $method_map = array();
function DB_Connection() {
$this->loadFeatureSet("basic");
}
function loadFeatureSet($name) {
include_once "DB/feature/{$name}.php";
$class = "DB_feature_{$name}";
$obj = &new $class;
foreach (get_class_methods($class) as $m) {
if ($m{0} != "_") {
$this->method_map[$m] = &$obj;
}
}
}
function __call($methodname) {
if (isset($this->method_map[$methodname])) {
return call_user_method_array($methodname,
array_slice(func_get_args(), 1));
}
}
}
overload("DB_Connection");
?>
The "basic" feature set contains only the minimal stuff: connect, query,
fetch results. You would use it like this:
<?php
$dbh = DB::connect($DSN);
// this creates a DB_Connection object, which loads the "basic"
featureset, registering
// methods like connect, disconnect, query and fetchInto. It then calls
the "connect" method
// in this object, which does not exist, but since the object is
overloaded, the __call method
// is called instead with "connect" as its first param and the rest of
the args following.
// __call checks the method map and finds the right object to proxy the
connect call to.
$sth = $dbh->query("SELECT foo FROM bar");
$sth->fetchInfo($row);
// Oops, you need to use sequences..
$dbh->loadFeatureSet("sequences");
$new_id = $dbh->nextId("myseq");
?>
What this does is use Andrei's new overloading extension (which is not
yet finished, but the concept still applies) to set up a class so
special handler methods are called when undefined methods or properties
are accessed. This basically turns the connection object into a call
proxy object. The catch is that all calls go through the __call method,
which more than doubles the function call overhead (I haven't measured
the impact). However, this class is so simple that a C version would be
trivial, and maybe even logical to have as a general class provided by
ext/overload.
- Stig