Page 2 of 3
Posted: Tue Jan 31, 2006 11:24 am
by Gambler
Speaking about database, I tend to use name-mapping hashes.
Code: Select all
<?php
$tableName = array(
'this' => 'tableName',
'fieldName1' => 'fieldName1',
'fieldName2' => 'zzzz',
);
?>
This may seem redundant first, but only until you start changing database for some reason.
That is a problem not just limited to __autoload() and is infact a problem that will never be solved.
*cough* Java *cough*
Posted: Tue Jan 31, 2006 1:41 pm
by Jenk
Oh, so Java automatically solves the global variable naming problems?
Didn't think so.
The problem here is NOT with __autoload() it is with the callsigns/names chosen by developers to call their classes/files/directory structures/variables etc. and the very fact we can all chose whatever name we like providing it falls within the usual limits of legal characters and is not a reserved word.
something even Java cannot solve
Please read entire posts when you fancy quoting for a nitpick.
Posted: Tue Jan 31, 2006 5:44 pm
by Christopher
Gambler wrote:Speaking about database, I tend to use name-mapping hashes.
Code: Select all
<?php
$tableName = array(
'this' => 'tableName',
'fieldName1' => 'fieldName1',
'fieldName2' => 'zzzz',
);
?>
This may seem redundant first, but only until you start changing database for some reason.
I would suggest encaptsulating that in a Data Mapper class. Then you can keep the interface consistent and do things like inherit basic select, update, insert, delete functionality from a base class.
Posted: Tue Jan 31, 2006 6:33 pm
by Christopher
Jenk wrote:The problem here is NOT with __autoload() it is with the callsigns/names chosen by developers to call their classes/files/directory structures/variables etc. and the very fact we can all chose whatever name we like providing it falls within the usual limits of legal characters and is not a reserved word.
You are right. And it gets worse with how PHP handles case with class names. You end up guessing or forcing to lowercase, but even tricks like PEAR style naming get fouled up with names like "Dir_ClassName" ending up as "Dir_Classname" or "dir_classname".
I think using the include path in conjunction with __autoload may simplify things. The thing I like about the include path is that it allows you to locally override classes by putting a dir with local classes in the include path before the "framework" dir.
Posted: Tue Jan 31, 2006 6:42 pm
by Ambush Commander
If all else fails, you could load an associative array of classnames to files...
Posted: Tue Jan 31, 2006 6:46 pm
by Christopher
Ambush Commander wrote:If all else fails, you could load an associative array of classnames to files...
Using a Registry as a class Factory is pretty common these days and is Service Locator.
Posted: Tue Jan 31, 2006 6:51 pm
by Ambush Commander
Err... fly that by me again?
A quick google turns up
http://java.sun.com/blueprints/corej2ee ... cator.html , but I'm wary on using Java patterns in PHP: the two language have their own bundle of problems.
Posted: Tue Jan 31, 2006 7:03 pm
by Christopher
Ambush Commander wrote:Err... fly that by me again?
Well there are two issues. One is finding the file that contains the class which is an old problem that usually requires some convention to solve cleanly. The other is Lazy Load which is a fairly unique problem in PHP. That's because the case where this comes up is for those objects that you want to instantiate in the code but not include the file if it is not needed. That's why implementing a PHP specific lazy class loader using Registery/ServiceLocator type solution makes a lot of sense. It solves both issues in a testable way. And it gets you a little lightweight Dependency Injection to boot.
A quick google turns up
http://java.sun.com/blueprints/corej2ee ... cator.html , but I'm wary on using Java patterns in PHP: the two language have their own bundle of problems.[/quote]I don't know about calling the Java patterns because the impementations (and even motivations for use) are different between PHP and Java. There are many patterns that are useful for web development that were first widely written about by Java developers. This would be a better read on the subject:
http://www.martinfowler.com/articles/injection.html
Posted: Wed Feb 01, 2006 8:51 am
by Buddha443556
To me, a ServiceLocator seems like a rather heavy solution to the problem of finding the right class file on a per request basis. I may just have the wrong impression of the pattern though.
Posted: Wed Feb 01, 2006 11:15 am
by Christopher
Buddha443556 wrote:To me, a ServiceLocator seems like a rather heavy solution to the problem of finding the right class file on a per request basis. I may just have the wrong impression of the pattern though.
It's is actually a pretty lightweight container in PHP. It is used frequently these days in frameworks rather than passing Request/Response objects around (which is the old Java framework style). You get a simple, testable interface to access objects that are needed several places/layers. You can either register classes up front, add class loader code (like __autoload() ), or work in conjunction with __autoload(). You end up with a little Dependency Injection in PHP using only a small code. In PHP4 it should be as simple as:
Code: Select all
class ServiceLocator {
var $_instance = array();
function & get ($name) {
if (isset($this->_instance[$name])) {
// add __autoload() style Lazy Load code here
$obj = &$this->_instance[$name];
} else {
$obj = NULL;
}
return $obj ;
}
function set ($name, &$obj) {
$this->_instance[$name] = &$obj;
}
function has ($name) {
return isset($this->_instance[$name]};
}
}
Posted: Wed Feb 01, 2006 11:50 am
by Buddha443556
The dynamic ServiceLocator is certainly more appealing than the static version. However, even the dynamic ServiceLocator is a far cry from a simple include() or __autoload(). If it can eliminate relative includes then there probably a benefit there somewhere (or it at least balances out in the end).
Posted: Wed Feb 01, 2006 12:35 pm
by Christopher
Buddha443556 wrote:The dynamic ServiceLocator is certainly more appealing than the static version.
I agree and try to stay away from statics and Singletons because I find that I usually need to change them anyway.
Buddha443556 wrote:However, even the dynamic ServiceLocator is a far cry from a simple include() or __autoload(). If it can eliminate relative includes then there probably a benefit there somewhere (or it at least balances out in the end).
I tend to use it as a container rather than a loader. I have moved away from using __autoload() because it is magic and causing testing problems for me. I tend to think that loading should be handled by some object rather than just inline -- which would indicate a design issue to me.
Posted: Thu Feb 02, 2006 2:47 pm
by Gambler
Hm...
Code: Select all
<?php
function make($class, $args = array()){
include_once("dir/$class.php"); //or something like this
$argsCode = array();
foreach (array_keys($args) as $key) {
$argsCode[] = "\$args[$key]";
}
$code = "return new $class(" . join(', ', $argsCode) . ");";
return eval($code);
}
?>
Unfortunately this would not preserve references, and would slow things down in case if many objects need to be created.
Jenk wrote:Oh, so Java automatically solves the global variable naming problems?
I don't think this part of discussion is headed in a good direction.
arborint, your ServiceLocator returns objects only if they've been set, right? So how can it load classes? I mean, if object is already set, what would you need to load?
Posted: Thu Feb 02, 2006 4:08 pm
by Christopher
Gambler wrote:arborint, your ServiceLocator returns objects only if they've been set, right? So how can it load classes? I mean, if object is already set, what would you need to load?
Well you could add something like the code you posted. Here is a quick, untested hack to demonstrate. This assumes that you are using include_path, but you could put some path scheme in of you wanted. I'm not sure that I like the interface for get() but it might be ok.
Code: Select all
<?php
class ServiceLocator {
var $_instance = array();
function & get ($name, $class='', $args=array()) {
$obj = NULL;
if (! isset($this->_instance[$name])) {
if ($class && ! class_exists($class)) {
include_once("$class.php"); //or something like this
}
if (class_exists($class)) {
if ($args) {
foreach (array_keys($args) as $key) {
$argsCode[] = "\$args[$key]";
}
$argsStr = join(', ', $argsCode);
} else {
$argsStr = '';
}
eval("\$this->set('$name', new $class($argsStr));");
}
}
if (isset($this->_instance[$name])) {
$obj = &$this->_instance[$name];
}
return $obj ;
}
function set ($name, &$obj) {
$this->_instance[$name] = &$obj;
}
function has ($name) {
return isset($this->_instance[$name]);
}
}
$sl =& new ServiceLocator();
$obj =& $sl->get('name', 'Class');
print_r($obj);
?>
Posted: Fri Feb 03, 2006 4:02 pm
by Gambler
Okay, now I get it. Thanks.
...
Does anyone know how to re-write my make() function without eval and reference loss?