Code: Select all
<?php
$tableName = array(
'this' => 'tableName',
'fieldName1' => 'fieldName1',
'fieldName2' => 'zzzz',
);
?>*cough* Java *cough*That is a problem not just limited to __autoload() and is infact a problem that will never be solved.
Moderator: General Moderators
Code: Select all
<?php
$tableName = array(
'this' => 'tableName',
'fieldName1' => 'fieldName1',
'fieldName2' => 'zzzz',
);
?>*cough* Java *cough*That is a problem not just limited to __autoload() and is infact a problem that will never be solved.
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.Gambler wrote:Speaking about database, I tend to use name-mapping hashes.
This may seem redundant first, but only until you start changing database for some reason.Code: Select all
<?php $tableName = array( 'this' => 'tableName', 'fieldName1' => 'fieldName1', 'fieldName2' => 'zzzz', ); ?>
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".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.
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.Ambush Commander wrote:Err... fly that by me again?
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: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.
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]};
}
}I agree and try to stay away from statics and Singletons because I find that I usually need to change them anyway.Buddha443556 wrote:The dynamic ServiceLocator is certainly more appealing than the static version.
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.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).
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);
}
?>I don't think this part of discussion is headed in a good direction.Jenk wrote:Oh, so Java automatically solves the global variable naming problems?
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.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?
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);
?>