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) コードを書き直さずに monolog 以外の別のロガーに切り替えることはできません。
3) if ステートメントだけで区切られたクラス/特性定義が重複しているため、IDE が完全に混乱します。
Symfony らがこの問題を解決する方法は、サービス層を持つことです。ただし、依存関係の包含を、オプションのモジュールを導入する場合よりもはるかに複雑にすることなく、その設計パターンを使用する方法がわかりません。
オプションのモジュールを含めたり、それらを他の互換性のあるモジュールに置き換えたりするための適切な設計パターンを説明できる人はいますか? それとも、これは実際のフレームワーク内でのみ適切に定義できるタイプのものですか?