类的非显式扩展?

时间:2011-02-23 00:56:36

标签: php oop class extension-methods

方案
系统具有在/system/classes/中声明的类 应用程序具有在/application/classes/中声明的类。

如果 application 文件夹中的类与 system 文件夹中的类同名,则应用程序中的类文件夹应该扩展 system 文件夹中的类。

system 文件夹中的所有类都不会被 application 文件夹中的类覆盖。

问题
如果中有一个类,如何使 system 文件夹中的类扩展应用程序 中的类?应用程序文件夹。

NB:所有可以覆盖的类都是静态类
NB:即使我们必须将应用程序类命名为 my_className ,也可以,只要我们仍然可以调用className::functionName()

我想我正在寻找类似Code Igniter的方法。

<小时/> 的修改

示例类
下面的类用作加载器以加载所有其他类(无论是库,进程还是其他类)。它还用于加载css / image / js文件等。

如果用户要扩展该类,他们可能希望添加ini()函数,该函数将用于加载ini个文件。

class load {

    protected static $helpers;
    protected static $configs;
    protected static $libraries;
    protected static $processes;
    protected static $js;
    protected static $css;

    public static function init() {
        self::$helpers = new stdClass();
        self::$libraries = new stdClass();
        self::$configs = new stdClass();
        self::$processes = new stdClass();
        self::$css = new stdClass();
        self::$js = new stdClass();
    }

    public static function config($name) {
        if (isset(self::$configs->$name) && is_object(self::$configs->$name))
            return self::$configs->$name;

        if (is_file(CONFIG_DIR . $name . '.php')) {
            require_once(CONFIG_DIR . $name . '.php');
            self::$configs->$name = new $name();
            return self::$configs->$name;
        }
        throw new exception('Could not load config file \'' . $name . '\'');
        return false;
    }

    public static function helper($name) {
        if (isset(self::$helpers->$name) && is_object(self::$helpers->$name))
            return self::$helpers->$name;

        if (is_file(APP_HELPER_DIR . $name . '.php')) {
            require_once(APP_HELPER_DIR . $name . '.php');
            self::$helpers->$name = new $name();
            return self::$helpers->$name;
        }

        if (is_file(HELPER_DIR . $name . '.php')) {
            require_once(HELPER_DIR . $name . '.php');
            self::$helpers->$name = new $name();
            return self::$helpers->$name;
        }
        throw new exception('Could not load helper file \'' . $name . '\'');
        return false;
    }

    public static function library($name, $params = array()) {
        if (empty($params) && isset(self::$libraries->$name) && is_object(self::$libraries->$name))
            return self::$libraries->$name;

        if (is_file(APP_LIBRARY_DIR . $name . '.php')) {
            require_once(APP_LIBRARY_DIR . $name . '.php');
            self::$libraries->$name = new $name($params);
            return self::$libraries->$name;
        }

        if (is_file(LIBRARY_DIR . $name . '.php')) {
            require_once(LIBRARY_DIR . $name . '.php');
            self::$libraries->$name = new $name();
            return self::$libraries->$name;
        }
        throw new exception('Could not load library file \'' . $name . '\'');
        return false;
    }

    public static function process($name, $args = array()) {
        if (isset(self::$processes->$name) && is_object(self::$processes->$name))
            return self::$processes->$name;

        if (is_file(PROCESS_DIR . $name . '.php')) {
            require_once(PROCESS_DIR . $name . '.php');
            if (empty($args)) {
                self::$processes->$name = new $name();
                return self::$processes->$name;
            } else {
                self::$processes->$name = new ReflectionClass($name);
                return self::$processes->$name->newInstanceArgs($args);
            }
        }
        throw new exception('Could not load process file \'' . $name . '\'');
        return false;
    }

    public static function css($name) {
        if (isset(self::$css->$name) && !empty(self::$css->$name))
            return self::$css->$name;

        self::$css->$name = '<link rel="stylesheet" type="text/css" href="' . CSS_PATH . $name . '.css">';
        return self::$css->$name;
    }

    public static function js($name) {
        if (isset(self::$js->$name))
            return self::$js->$name;

        self::$js->$name = '<script src="' . JS_PATH . $name . '.js"></script>';
        return self::$js->$name;
    }

    public static function template($name, $vars = array()) {
        if (is_file(TEMPLATE_DIR . $name . '.php')) {
            ob_start();
            if (!empty($vars))
                extract($vars);
            require(TEMPLATE_DIR . $name . '.php');
            $contents = ob_get_contents();
            ob_end_clean();
            return $contents;
        }
        throw new exception('Could not load template file \'' . $name . '\'');
        return false;
    }

}

1 个答案:

答案 0 :(得分:1)

据我所知,代码Igniter会替换类,而不是扩展它们。

更实际的方法是动态生成代码:

$code = file_get_contents($appFile);
if ( file_exists( $systemFile ) )
{
    //don't do this ! Just a proof of concept, use regexp or code tokenizer
    //you will also need to programmatically determine MyClass and SystemClass
    $code = str_replace ('class myClass', 'class MyClass extends SystemClass', $code);
}
eval ($code)

请注意,eval通常被认为是邪恶的,因此请务必仔细检查您的代码。 您可能希望重新考虑您的框架设计。

更新:如果类只是静态的,您可能需要查看 Decorator 模式和__call()__ get()__ set()。这可能足以避免eval()路由。