我正在编写一些代码(数据库抽象层,用于我的其他代码模块),我想将其作为独立模块发布,可以包含在 composer 的项目中。我想在作曲家定义中包含一些可以提高我的模块性能的建议模块,但这不是必需的。
我遇到的问题是如何以一种完全可怕的方式做到这一点。
因此,在这个特定的示例中,模块被声明,namespace Intahwebz\DB;
然后Intahwebz\Log\Log
尝试包含可选模块,然后尝试使用可选模块Monolog
。
到目前为止我所拥有的是模块代码 ConnectionWrapper.php
namespace Intahwebz\DB;
use Intahwebz\Log\Log;
if(trait_exists("Intahwebz\Log\Log") == 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 中检查 Monolog 是否可用,如果可用,则包含它,否则定义一个真正轻量级的记录器。
<?php
namespace Intahwebz\Log;
if (class_exists('Monolog\Logger') &&
class_exists('Monolog\Handler\StreamHandler')) {
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__);
}
}
}
如果 Monolog 可用,我们通过包含 MonologWrapper.php 来使用它
<?php
namespace Intahwebz\Log;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
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) 它具有重复的类/特征定义,仅由 if 语句分隔,这完全混淆了我的 IDE。
我知道 Symfony 等人解决这个问题的方法是拥有一个服务层。但是,如果不强制依赖包含比引入可选模块应该复杂得多,我看不出如何使用该设计模式。
谁能描述一个体面的设计模式来包含可选模块,或者用其他兼容模块替换它们?或者这是只能在实际框架中很好地定义的事物类型?