PHP Composer,用于包含带有名称空间的建议模块的良好设计模式



我正在编写一些代码(数据库抽象层,在我的其他代码模块中使用),我想作为一个独立的模块发布,可能包含在一个项目与作曲家。我想在编写器定义中包含一些建议的模块,这些模块可以提高我的模块的性能,但这不是必需的。

我的问题是如何以一种不完全可怕的方式做到这一点。

因此,在这个特定的示例中,模块在namespace IntahwebzDB;中声明,然后尝试包含可选模块IntahwebzLogLog,这反过来又尝试使用可选模块Monolog

我现在看到的是模块代码connectionwrapper。php

namespace IntahwebzDB;
use IntahwebzLogLog;

if(trait_exists("IntahwebzLogLog") == false){
    require_once("Log.php");
}

class ConnectionWrapper{
    use Log;
    function __construct(){
        $this->initLog();
        // Rest of constructor code.
        $this->log->trace("ConnectionWrapper has been constructed.");
    }   
    // Lots of other functions here.
}

?>  

然后在Log.php中检查是否有可用的独白,如果有,包括它,否则定义一个真正轻量级的记录器。

<?php
namespace IntahwebzLog;
if (class_exists('MonologLogger') &&
    class_exists('MonologHandlerStreamHandler')) {
require_once "MonologWrapper.php";
}
else{
    class Logger{
        public function debug($message, array $context = array()){
            echo $message."n";
        }
        public function log($level, $message, array $context = array()){
            echo $message."n";
        }
        public function info($message, array $context = array()){
            echo $message."n";
        }
        public function notice($message, array $context = array()){
            echo $message."n";
        }
        public function warning($message, array $context = array()){
            echo $message."n";
        }
        public function error($message, array $context = array()){
            echo $message."n";
        }
        public function critical($message, array $context = array()){
            echo $message."n";
        }
        public function alert($message, array $context = array()){
            echo $message."n";
        }
        public function emergency($message, array $context = array()){
            echo $message."n";
        }
    }
    trait Log{
        var $log;
        function initLog(){
            $this->log = new Logger(__CLASS__);
        }
    }
}

如果独白可用,我们通过包含MonologWrapper.php来使用它

<?php
namespace IntahwebzLog;
use MonologLogger;
use MonologHandlerStreamHandler;
trait Log{
    var $log;
    function    initLog(){
        $this->log = new Logger(__CLASS__);
        //Todo - get log handler from config file automagically.
        $this->log->pushHandler(new StreamHandler(PATH_TO_ROOT.'var/log/Admin.log', Logger::WARNING));
    }
}

?>

问题是:

1)它非常丑陋,并且每个建议的模块需要额外的文件。

2)它不允许人们在不重写代码的情况下切换到独白以外的其他记录器。

3)它有重复的类/trait定义,只有if语句分开,这完全混淆了我的IDE。

我知道Symfony等解决这个问题的方法是通过一个服务层。然而,我不知道如何使用这种设计模式,而不强迫依赖项包含比引入可选模块更复杂。

谁能描述一个体面的设计模式,包括可选模块,或者用其他兼容模块替换它们?或者这类东西只能在一个实际的框架中很好地定义?

依赖注入:)

例如,不用

function    initLog(){
    $this->log = new Logger(__CLASS__);
    // ..
}
使用

function setLogger(Logger $logger) {
    $this->log = $logger;
    // ...
}

以此类推。有太多的硬编码依赖,我不会一一提到。

class MonologLoggingConnectionWrapperWrapper extends ConnectionWrapper {
    public function __construct (ConnectionWrapper $wrapper, Logger $logger) {
        // ..
    }
}

现在独白是必需的,当有人试图实例化这个类,然后很明显,有些东西丢失了。如果您愿意,您可以在类定义之前向文件添加一个测试,这应该(在这种情况下)抛出一个异常,或触发一个错误。

(类名源于ConnectionWrapper不是一个真正的包装器,而是一个独立的类:包装器必须扩展被包装的类,或实现相应的接口,因此它是干净的可交换的)

值得一提的是:避免条件类或函数定义:)一个Classname,一个类(不能更多),当我试图实例化一个类时,它要么存在,要么不存在,但不是"有时"。

相关内容

  • 没有找到相关文章

最新更新