通过管理复杂的php oop应用程序,我有点不知所措。在过去,我已经为我的'utils'类使用了静态方法,但是我正在编写一个新的应用程序,我希望编写尽可能高的标准代码,所以我希望尽可能避免使用它们。保持可测试性等。
我看过依赖注入,但我打算创建一个帮助类的'库'(可以这么说),我可以毫不费力地放入项目中。我的问题是,因为我可能有五六个,我真的不想设置用户需要将所有这些对象传递到的构造。
我的研究把我带到了工厂 - 我创造了这样的野兽,但我真的不知道这是不是正确的做事方式。它有点像这样......
class Create {
private static $validation = null;
private static $helper = null;
private static $html = null;
private static $form = null;
public static $user = null;
public static $db = null;
// --------------------------------------------------------------
// Initialize
// --------------------------------------------------------------
public static function load($object, $options, $dependencies = array('html', 'helper', 'db', 'user')) {
// Create specified object (without constructor)
// PHP version < 5.4
$$object = self::createInstanceWithoutConstructor($object);
// Inject specified options into new object
foreach($dependencies as $dependency):
if(is_null(self::$$dependency)): self::$$dependency = new $dependency; endif;
$$object->$dependency = self::$$dependency;
endforeach;
// Now call the constructor
// PHP version < 5.4
if(method_exists($$object, '__construct')):
$$object->__construct($options);
endif;
return $$object;
}
// --------------------------------------------------------------
// Create Instance of Object Without Calling it's Constructor
// --------------------------------------------------------------
// Workaround for PHP version < 5.4
// This will be updated to use
// ReflectionClass::newInstanceWithoutConstructor
// when 5.4 is more freely supported
// --------------------------------------------------------------
private static function createInstanceWithoutConstructor($class) {
$reflector = new ReflectionClass($class);
$properties = $reflector->getProperties();
$defaults = $reflector->getDefaultProperties();
$serealized = "O:" . strlen($class) . ":\"$class\":".count($properties) .':{';
foreach ($properties as $property){
$name = $property->getName();
if($property->isProtected()){
$name = chr(0) . '*' .chr(0) .$name;
} elseif($property->isPrivate()){
$name = chr(0) . $class. chr(0).$name;
}
$serealized .= serialize($name);
if(array_key_exists($property->getName(),$defaults) ){
$serealized .= serialize($defaults[$property->getName()]);
} else {
$serealized .= serialize(null);
}
}
$serealized .="}";
return unserialize($serealized);
}
// --------------------------------------------------------------
// Create User
// --------------------------------------------------------------
public static function User($options = array()) {
$user = self::load(__FUNCTION__, $options);
return $user;
}
// --------------------------------------------------------------
// Create Page
// --------------------------------------------------------------
public static function Page($options = array()) {
$page = self::load(__FUNCTION__, $options);
return $page;
}
// --------------------------------------------------------------
// Create Form
// --------------------------------------------------------------
public static function Form($name, $method = 'POST', $action = null, $attributes = array()) {
// Check to see if form was submitted
// If so, get form object, otherwise create new form object
if(isset($_POST[$name])):
$form = unserialize($_SESSION['formObj']);
$form->errors = array();
$form->rule = $form->rule;
$form->labels = $form->labels;
$form->errors = $form->errors;
else:
$form = self::load(__FUNCTION__, array(), array('html', 'validation'));
$form->name = $name;
endif;
// Open the form
$form->open($method, $action, $attributes);
return $form;
}
}
因此它具有用于创建各种对象的单独函数,除非明确设置依赖关系,否则传递默认选择。
现在,我真的不确定这是否是一个好的方法,从更多的研究,我已经收集了为每个类负责在该类中创建对象的一个工厂可能是一个更好的主意。这是接近这个的更“正确”的方式吗?如果是这样,那些工厂方法(不确定这是否是正确的术语?)只是可以在任何地方调用的静态,或者它们只是创建新对象然后传递它们的常规方法吗?这还需要扩展一个“Factory”类来保存创建的对象吗?
希望一切都有意义,任何和所有帮助都将受到赞赏。
此致,
困惑的N00b。
答案 0 :(得分:3)
查看您的代码并阅读您的帖子,我觉得您过于复杂。
您无需关注什么是“正确”的做事方式。做某事的正确方法是最适合您给定方案的方式。看看你需要做什么,展望未来(但不要太远!!),并尝试找到一个没有过度设计的解决方案,但给你增长的空间。
我说未来不太远,因为开发人员往往过于沉迷于他们的设计,试图计划每一种可能的可能性,并最终得到一个无法维护的怪物。
如果静态类中包含的一系列工厂函数对您有用,并且您不会很快预见到任何重大问题,为什么还需要继续设计?要学会做的最难的事情之一就是在为未来设计和完成任务之间走一条路:)
答案 1 :(得分:0)
您列出的内容似乎是制作服务定位器的不良尝试。这是一种注册表模式。 每个班级都应该有一定的目的。 因此,使ServiceLocator类和工厂类/方法的数量返回实例。然后在应用程序启动时将它们设置为ServiceLocator。