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

关于PHP类的一些(高级)问题,php,class,Php,Class,我有几个关于PHP类的问题,但不能单独问,所以我来问: 我有一个CMS,我正在建设,在它的核心是我的基类,记录器,数据库和模块类。DB和logger是静态类,所以我可以在其他对象中使用它们。有许多模块类通过以下方式加载到基类中: class baseClass { private $_modules; public function __construct() { logger::log("instance created."); $this-

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

我有一个CMS,我正在建设,在它的核心是我的基类,记录器,数据库和模块类。DB和logger是静态类,所以我可以在其他对象中使用它们。有许多模块类通过以下方式加载到基类中:

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实现是个好主意还是您有更好的解决方案。或者可以反过来扩展一个类,这样我就不必加载模块,相反,它们的类定义将自己加载到基类中,如:

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:现在我将我的logger和DB类用作静态类(我用logger::和DB::)调用它们)因此,它们可以从任何上下文和范围访问-是否可以实例化它们并在我的基类对象中使用它们,但不必在基类中实例化它们或在我将使用它的每个类中设置它们:

public function __construct() {
    global $logger_instance;
    $this->logger = $logger_instance;
}
我尝试过不同的方法,从在基类内传递原始对象引用的糟糕方法到使用包装函数的丑陋方法。当基类未设置且很难通过模块访问时,使用引用将销毁我的记录器对象-$this->base->logger->log()-这反过来需要对基类对象的引用($this->base),并在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>
类标记创建者{
公共函数createTag($tag$data){
$tag1=$tag;
$tag2='/'.$tag;
返回“$data”;
}
}
类样式功能{
公共函数构造(){
//如果类已加载(tagCreator)|加载类(tagCreator)
//在这里施展点魔法来保护造物主
//tagCreator->createTag->添加参数$style
//tagCreator->createTag->$tag1+='style=“.”.$style.''
//否则问题错误tagCreator不存在
}
}
$instance=新基类();
$instance->loadModule('tagCreator');
echo$instance->createTag('span','some string');
//返回一些字符串
$instance->loadModule('styleFunctionality');
echo$instance->createTag('span','some string','font-weight:bold');
//返回一些字符串
注意:我不一定是指函数重载,我可能只想更改方法内部的一点代码

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


很抱歉话题太长,感谢您阅读到此为止,我甚至希望您能回答我的一个问题:)

Q1-我将使用加载来加载课程。您可以解析类名,找出您试图加载的类的位置和类型(例如控制器、模块、插件等)

\uu get()
(在基类中)结合使用,您将能够像
$instance->moduleX->f1()那样调用您的模块如果你想的话

Q2-我也将静态类用于此类活动。除了有一个全局可用的变量(在其他方面有与代码冲突的风险)之外,您没有什么其他的方法可以做

Q3-有一种模式类似于你试图实现的目标,但就我而言,我现在似乎记不起来了。但实际上,您需要在主类中注册修饰符类。查看应用程序的结构,您可以通过查看基类模块数组或将修改器类传递给主类(
tagCreator
)来了解这一点

无论您决定如何操作,都需要在返回输出之前修改
createTag()
方法以查找加载的修改器类(
styleFunctionality
)。您的修饰符类当然需要某种标准接口供您的主类调用


警告一句,看看您是如何将模块加载到同一个实例中的。如果两个类定义了相同的方法,则可能会发生冲突。我建议您分别访问它们,如<代码> $> -MexEng> > Athood()/代码> ./P> < P>数据库和日志记录器,我将考虑使用单模式。p>
<?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-您可以使用自动加载按需加载类,这样您就可以使用第二种调用方法
$instance->moduleY->f4()。Q2-我认为静态方法是实现这一点的方法。我想到了这一点,但有时我可能会声明所有模块,但我不希望它们都加载到我的基类中。我回答得更详细。你不应该加载到第三季度的基类中,我想你在寻找工厂模式?@preinheimer-no,不是工厂模式。这有利于创建对象。让我们看看谷歌带来了什么up@preinheimer我看到了,和我想的差不多。但不是很合适,因为他会在加载类时修改内容。但是