【发布时间】:2013-08-16 12:15:12
【问题描述】:
管理一个复杂的 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;
}
}
因此它具有用于创建各种对象的单独功能,除非明确设置依赖关系,否则会传入默认选择。
现在,我真的不确定这是否是一种好方法,从更多的研究中,我收集到为每个负责在该类中创建对象的类拥有一个工厂可能是一个更好的主意。这是更“正确”的处理方式吗?如果是这样,那些工厂方法(不确定这是否是正确的术语?)是否应该只是可以在任何地方调用的静态方法,或者它们可以只是创建新对象然后传递它们的普通方法?这是否还需要扩展一个包含已创建对象的“工厂”类?
希望一切都有意义,任何和所有帮助将不胜感激。
你的,
困惑的 N00b。
【问题讨论】:
-
只是一个小提示:名称为动词的类要么命名错误,要么 - 大多数情况下 - 封装错误。动作(动词)不是对象(名词)。
-
如果你的类有太多的依赖,那么很明显,你的类有太多的责任。与其添加一些魔法,不如尝试修复这些类。另外,
$$object的意义何在?为什么不能直接叫它$instance,因为它是一个局部变量,它的名字在函数之外没有任何影响。 -
我不认为我的类有太多责任,我希望我的“帮助”类在整个应用程序中都可以轻松使用。我只是发现在尝试避免静态类时很难允许。至于 $object - $instance 可能更有意义。谢谢指点。