在构造函数中使用不同数量的参数自动加载类

时间:2014-02-12 21:49:01

标签: php reflection factory autoloader

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

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

/**
 * 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));

对上面代码的所有部分的评论很好,但我真的在寻找更好的解决方案。迟早,我会遇到一个有五个参数的课程并且“返回新的$ class($ p [0],$ p [1],$ p [2],$ p [3]);”已经让我很恼火。

1 个答案:

答案 0 :(得分:2)

简单:

return $reflection->newInstanceArgs($p);