关于PHP类的一些(高级)问题

我有几个关于PHP类的问题,但不能单独询问,所以我在这里:

我有一个CMS,我正在构建,其核心是我的baseClass,记录器,数据库和模块类。 DB和记录器是静态类,所以我可以在其他对象中使用它们。 有很多模块类被加载到baseClass中:

class baseClass {
    private $_modules;

    public function __construct() {
        logger::log("instance created.");
         $this->_modules = Array()
    }

    public function __destruct() {
        foreach($this->_modules as $name) $this->unloadModule($name);
        logger::log("instance destroyed.");
    }

    public function loadModule($name) {
        if (class_exists($name)) {
            if (!isset($this->$name)) {
                $this->_modules[] = $name;
                $this->$name = new $name();
                logger::log("module '$name' loaded.");
            }
            else logger::log("module '$name' already loaded.", 2);
        }
        else logger::log("module '$name' does not exist.", 3);
    }

    public function unloadModule($name) {
        if (isset($this->$name)) {
            unset($this->$name);
            foreach($this->_modules as $id => $mod_name) {
                if ($name==$mod_name) {
                    unset($this->_modules[$id]);
                    logger::log("module '$name' unloaded.");
                }
            }
        }
        else logger::log("module '$name' not loaded.", 2);
    }

    public function listModules() {
        return $this->_modules;
    }
}
$instance = new baseClass();
$instance->loadModule('moduleX');
$instance->loadModule('moduleY');

问题1:我的loadModule实现是一个好主意,或者你有更好的解决方案。 或者有可能以其他方式扩展一个类,所以我不必加载模块,而是他们的类定义会将自己加载到baseClass中,如下所示:

class moduleX reverseExtends baseClass {
    public function f1();
    public function f2();
}
class moduleY reverseExtends baseClass {
    public function f3();
    public function f4();
}

$instance = new baseClass();
$instance->f1();
$instance->f2();
$instance->f3();
$instance->f4();

或者至少:

$instance->moduleX->f1();
$instance->moduleX->f2();
$instance->moduleY->f3();
$instance->moduleY->f4();

问题2:现在我使用我的记录器和DB类作为静态类(我使用logger ::和DB::)调用它们,以便它们可以从任何上下文和范围访问 - 是否可以实例化它们并仍然在内部使用它们我的baseClass对象,但没有在baseClass中实例化它们,或者在每个类中将它们设置为这样,我将使用它:

public function __construct() {
    global $logger_instance;
    $this->logger = $logger_instance;
}

我已经尝试了不同的方法,比如将不同的方法从baseClass中的原始对象的引用传递给使用包装函数的丑陋。 当baseClass未设置并且很难通过模块访问时,使用引用会破坏我的记录器对象 - $ this-> base-> logger-> log() - 这需要引用baseClass对象($ this-> base)和杀死我的baseClass对象在unloadModule上......至于包装函数 - 我希望能够拥有多个logger对象实例,所以传递一个实例标识符和函数一起使它变得非常丑陋和“不真实”的解决方案。

我需要这样的东西:

public function someFuncionInsideSomeClass() {
    $logger->('Log something'); //or $logger('Log something') with __invoke()
    //$logger here is in the global scope
}

问题3:我希望一个模块能够修改另一个模块的代码。 例如,我有一个数据库模块加载,然后我加载一个记录模块,并希望记录模块集成到数据库模块代码中,而不必弄乱它的原始代码。 当然,记录器将不得不照顾整合本身(或者更确切地说我是编码器)。 简单的例子:

class tagCreator {
    public function createTag($tag,$data) {
        $tag1 = $tag;
        $tag2 = '/'.$tag;
        return "<$tag1>$data<$tag2>";
    }
}
class styleFunctionality {
    public function __construct() {
        //if class is loaded (tagCreator) | load class (tagCreator)
            //do some magic here to tagCreator
            //tagCreator -> createTag -> add argument $style
            //tagCreator -> createTag -> $tag1 += ' style="'.$style.'"'
        //else issue error tagCreator does not exist
    }
}
$instance = new baseClass();
$instance->loadModule('tagCreator');

echo $instance->createTag('span','some string');
// returns <span>some string</span>

$instance->loadModule('styleFunctionality');

echo $instance->createTag('span','some string','font-weight: bold');
// returns <span style="font-weight: bold">some string</span>

注意:我不一定是指函数重载,我可能只想改变方法中的一小段代码

注2:调用$ instance-> createTag()不是一个错误 - 我计划为baseClass编写一些花哨的__call()函数以从其加载的模块中选择方法

对不起,长话题和感谢阅读这个,我甚至会感激只有我的一个问题的答案:)


对于数据库和记录器,我会考虑使用单例模式。

<?php
class Singleton {
    private static $instance;

    private function __construct() {
        // no-op
    }
    /**
     * Create the instance or return the instance if it has already been created.
     *
     * @return object
     */

    static public function get_instance() {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }
        return self::$instance;
    }
}

?>

一般来说,你可能想看看需要PHP5的PHP框架,比如Kohana。 而且,就模式和PHP而言,您可能希望签出“PHP对象,模式和练习”。


Q1 - 我将使用自动加载器功能来加载类。 你可以解析类名来找出你要加载的类的位置和类型(例如 - 控制器,模块,插件等)。

结合__get() (在你的基类中),你将能够调用你的模块,如$instance->moduleX->f1(); 如果你想。

Q2 - 我也为这些活动使用静态类。 除了拥有一个全球可用的变量 - 在其他领域有与您的代码相冲突的风险之外,您无法做其他事情。

Q3 - 有一种类似于你想要达到的东西的模式,但是对于我的生活,我现在似乎无法记住它。 但它是如何发生的,你需要在你的主类中注册你的修饰符类。 看看你如何构建你的应用程序,你可以通过查看基类模块数组,或者通过将修饰符类传递给你的主类( tagCreator )来获得。

不过,您决定这样做,您需要修改createTag()方法以在返回输出之前查找加载的修饰符类( styleFunctionality )。 你的修饰符类当然需要某种标准接口供你的主类调用。

一句警告,看着你如何将你的模块加载到同一个实例中。 如果两个类具有相同的方法定义,则可能会产生冲突。 我建议你像$this->ModuleA->aMethod()那样分别访问它们。

链接地址: http://www.djcxy.com/p/51933.html

上一篇: Some (advanced) questions around PHP classes

下一篇: pick from sibling directories?