たとえば、 ここまたはここで 、DIとは何かを読むことができます。
目標は、Production DIフレームワークを開発することではありませんでした。 そのような機能を最も便利に実装する方法を考えたかった(上記のPhemtoは 、たとえばMicrosoft Unityのメソッドよりも不便だと思われた)
実装されたオプションはコードで設定されます(他の実装のようにXML経由ではなく、誰かにとっては便利ですが)。
使用する各型は事前に登録する必要がありますが、たとえばPhemtoのように引数をリストする必要はありません-コンテナ自体がReflectionを通じてコンストラクタ引数の型を判別します。
実装自体(以下の例):
<?
class PUnityException extends RuntimeException {
}
class PUnity {
const PUNITY_SINGLETON = 2;
const PUNITY_SIMPLE = 1;
private $data;
private $attributes;
private $singletons;
/**
*
*
* @param string $type
* @param string $concreteInstance
* @param int $attr
*/
public function RegisterType($type, $concreteInstance, $attr = PUnity::PUNITY_SIMPLE) {
// To get exceptions if types are not exists
$typeReflection = new ReflectionClass($type);
$concreteReflection = new ReflectionClass($concreteInstance);
$ this ->data[$type] = $concreteReflection;
$ this ->attributes[$type] = $attr;
}
/**
*
*
* @param string $type
* @return sdtclass
*/
public function Resolve($type) {
if ($ this ->attributes[$type] == PUnity::PUNITY_SINGLETON)
{
$typeReflection = $ this ->data[$type];
try { // May be class is taking care of it's instace by itself?
$getInstance = $typeReflection->getMethod( 'getInstance' ); // Yes, it's a hardcoding...
return $getInstance->invoke( null );
} catch (ReflectionException $e) { }
if (isset($ this ->singletons[$type])) // Try get existing one
return $ this ->singletons[$type];
}
$instance = $ this ->resolver($type); // Resolve type
if ($ this ->attributes[$type] == PUnity::PUNITY_SINGLETON) // Take care of storing the object instance
{
$ this ->singletons[$type] = $instance;
}
return $instance;
}
/**
*
*
* @param string $type
* @return stdclass
*/
private function resolver($type) {
$typeReflection = $ this ->data[$type];
$ctr = $typeReflection->getConstructor();
$args = array();
if ($ctr != null ) // Constructor is defined
{
$ctrParams = $ctr->getParameters();
foreach ($ctrParams as $p) {
$cls = $p->getClass();
if (!isset($ this ->data[$cls->getName()])) // No nothing about needed type
throw new PUnityException( "Type {$cls->getName()} not registered. Use RegisterType first" );
else
array_push($args, $ this ->Resolve($cls->getName()));
}
}
return count($args) ? $typeReflection->newInstanceArgs($args) : $typeReflection->newInstance();
}
}
?>
* This source code was highlighted with Source Code Highlighter .
簡単な使用例:
interface ILogger {
public function Logstr($str);
}
class MyLogger implements ILogger {
public function Logstr($str) {
echo "MyLogger: {$str}" ;
}
}
class UsingLogger {
public function __construct(ILogger $myLogger) {
$myLogger->Logstr( " On the move..." );
}
}
$u = new PUnity();
$u->RegisterType( 'ILogger' , 'MyLogger' );
$u->RegisterType( 'UsingLogger' , 'UsingLogger' );
$logger = $u->Resolve( 'UsingLogger' );
* This source code was highlighted with Source Code Highlighter .
そして、これがシングルトーンの作り方です:
<?php
interface ILogger {
public function Logstr($str);
}
class MyTrickyLogger implements ILogger {
private $timeCreated;
public function MyTrickyLogger() {
$ this ->timeCreated = time();
}
public function Logstr($str) {
echo "I created at " .date( 'dmY H:i:s .' , $ this ->timeCreated). 'Message: ' .$str. "<br/>\n" ;
}
}
class UsingLogger {
public function __construct(ILogger $myLogger) {
$myLogger->Logstr( " On the move..." );
}
}
$u = new PUnity();
$u->RegisterType( 'ILogger' , 'MyTrickyLogger' , PUnity::PUNITY_SINGLETON);
$u->RegisterType( 'UsingLogger' , 'UsingLogger' );
$logger = $u->Resolve( 'UsingLogger' );
sleep(2);
$logger2 = $u->Resolve( 'UsingLogger' );
?>
* This source code was highlighted with Source Code Highlighter .