Hello, everybody.
Consider the following code:
class DB {
public function query( $sql) {
// ... some "magic" of DB querying
}
}
class DBReader {
public $DB;// instance of DB
public function __call( $methodName, $args) {
return call_user_func_array( array( $this, $methodName), $args);
}
protected function readSomething() {
$sql ='SELECT ...';
$result =$this->DB->query( $sql);
}
protected function readSomethingElse() {
// ... very similar to DBReader::readSomething()
}
// .... + other methods like DBReader::readSomething()
}
If you take a look at DBReader::readSomething(), you'll see that I am
referencing database object and performing query via "$this->DB->query()".
If you do a lot of database queries, your code becomes bloated with
"$this->DB->..." and usually gets not so well readable (at least for me).
Since I have a lot of methods, that are similar to DBReader::readSomething()
(which perform DB queries), I would like to optimize readability of the DB
querying code. Right now I would do it in the following way:
// 1) reference database object inside the method
$DB =$this->DB;
// 2) do whatever I need with the DB
$DB->query( $sql);
$DB->numRows();
// ... or whatever
This way the code looks nicer and is, in fact, shorter.
So I wonder if there is any way to import scope (symbol table) into the
method DBReader::readSomething()? By importing the variables into the
function body,
I would like to avoid the "1) reference database object inside the method"
step so that $DB becomes instantly available:
protected function readSomething() {
$sql ='SELECT ...';
$result =$DB->query( $sql);// like this
}
AFAIK, there is no such call_user_func* function that would allow importing
of symbol table into the called fn.
What I would expect to be possible:
public function __call( $methodName, $args) {
$scope =array( 'DB' =>$this->DB);
return call_user_func_array( array( $this, $methodName), $args, $scope);//
note the $scope array, that is being passed here
}
The effect of such call to call_user_func_array() I would expect to be
equivalent with same as regular call to call_user_func_array(), but with
additional
call to extract( $scope, EXTR_REFS) right at the top of the function's body.
Does anybody have some ideas how I can get this working?
If there is no way to get this working with current PHP feature set, then I
would like to propose to extend call_user_func_array() to support $scope
argument.
What do you think about this?
P.S.: don't ask why I don't just simply make DBReader::readSomething() to be
public method. That's not the case.
P.S.: a very similar scope importing technique I am using with the PHP
template files I use in my web projects. As you know, include() is,
literally, "injecting" code
from the file into the current scope, thus making current symbol available
to the included code:
index.php:
$x =5;
$y =10;
include("chart.php");
chart.php:
echo $x .',' .$y;
After processing index.php, the output would be "5,10".
P.S.: closures are capable of importing scope via use() statement:
$x =5;
$y =10;
$closure =function() use( $x, $y) {
echo $x .',' .$y;
};
$closure();// would give output "5,10"
so I suppose that technically importing scope is not a big deal from the PHP
internals perspective.
Dmitry.