【问题标题】:Autoload classes with varying number of parameters in constructor在构造函数中自动加载具有不同数量参数的类
【发布时间】:2014-02-12 21:49:00
【问题描述】:

我正在使用已用于部署多个网站的现有代码库。一些站点自定义了一些类。我已经构建了一个至少可以找到类的自动加载函数。不幸的是,有些类在构造函数中有不同数量的参数。此时要“正确”所有这些类以使它们具有相同的构造函数签名是不切实际的。

除了自动加载器(它正在工作)之外,我正在尝试构建一个将实例化基本类的工厂。工厂应该处理对“购物车”类的请求,并传回该特定站点上使用的任何购物车类的实例。构造函数中不同数量的参数混淆了代码。我正在寻找一种方法来清理最后一部分(请参阅下面代码中的 cmets)。

/**
 * find and instantiate an object of the type $classtype.
 * example usage: factory::instance('cart');
 *
 * @param string $classtype  the class to instantiate
 * @param array $options     optional array of parameters for the constructor
 * @return object
 * @throws Exception
 */
static public function instance($classtype, $options = array()) {

    // so you request an instance of 'cart'
    // if CART_CLASS is defined, we set the class name to the value of that constant
    // if CART_CLASS is not defined, we set the class name to basic_cart
    $define = strtoupper("{$classtype}_CLASS");
    $class = defined($define) ? constant($define) : strtolower("basic_$classtype");

    $reflection = new ReflectionClass($class); // autoload function kicks in here to find the class

    // get the parameter list for the constructor
    $parameters = $reflection->getConstructor()->getParameters();

    $p = array();
    foreach($parameters as $parameter) {
        if(array_key_exists($parameter->name, $options)) {
            // making sure the order is correct by creating a new array
            $p[] = $options[$parameter->name];
        } else {
            if($parameter->isOptional()) {
                break; // todo: get the default value and pass that on instantiation
            } else {
                throw new Exception("required parameter '{$parameter->name}' was not provided in the options array when loading $class");
            }
        }
    }

    // todo: there must be a better way to pass a variable number of parameters
    if(count($p) == 1) {
        return new $class($p[0]);
    } else if(count($p) == 2) {
        return new $class($p[0], $p[1]);
    } else if(count($p) == 3) {
        return new $class($p[0], $p[1], $p[2]);
    } else if(count($p) == 4) {
        return new $class($p[0], $p[1], $p[2], $p[3]);
    } else {
        return new $class();
    }

}

下面是一个实例的“请求”示例。

$c = factory::instance('cart');
$s = factory::instance('ship_controller', array('cart' => $c));

对上面代码的所有部分的评论都很好,但我真的在为最后一部分寻找更好的解决方案。迟早会碰到一个有五个参数的类,“return new $class($p[0], $p[1], $p[2], $p[3]);”已经烦我了。

【问题讨论】:

    标签: php reflection factory autoloader


    【解决方案1】:

    就这么简单:

    return $reflection->newInstanceArgs($p);
    

    【讨论】:

    • 啊!美丽的!谢谢一百万。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 2012-02-02
    • 1970-01-01
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多