2

私は、Pimpleを使用してDIを使い慣れていません。使用:php 5.3.5(wamp)、名前空間も同様です。 私は、コードをリファクタリングそれを使用して、問題(複数可)に来たんだ:ピンプルを使用したPHPの依存性注入

class ReuseableContainer extends Pimple{ 

     private function initOutterClass(){ 
     $this['special_location_class'] = '\SpecialLocation'; 
     $this['special_location'] = function($c){return new $c['special_location_class']($c['location_details'],$c['location']);}; 
     } 

     private function initGlobalFunctions(){ 
     $this['getGeneralDataFromArray'] = function($c){ 
      // returning a function 
      return function($arr){ 
       foreach ($arr as $key => $value){ 
       // do something 
        $new_data = $c['general_data_type']; 
        $new_data->id = $value['id']; 
        $new_data->name = $value['name']; 
       } 

     }   

     } 

     public function __construct(){ 
      $this['location_class'] = '\Location'; 
      $this['location_details_class'] = '\LocationDetails'; 
      $this['general_data_type_class'] = '\GeneralDataType'; 
      // define some objects 
      $this['location'] = function ($c) { 
       return new $c['location_class'](); 
      }; 

      $this['location_details'] = function ($c) { 
       return new $c['location_details_class'](); 
      }; 

      $this['general_data_type'] = function ($c) { 
       return new $c['general_data_type_class'](); 
      }; 

      $this->initOutterClass(); 
      $this->initGlobalFunctions(); 
     } 



} 
global $container ; 
$container = new Pimple(); 

// embed the SomeContainer container 
$container['embed'] = $container->share(function() { return new ReuseableContainer(); }); 

OK:

私はにきびから延び私のコンテナを持って、PContainer.phpそれを呼び出すことができます。だから私は成り立つSpecialHelper.phpました:

final class SpecialLocation{ 
    public $name; 
    public $location; 
    public $picture; 

    public function __construct($location){ 
     $this->location; // dependent on class: Location 
    } 
} 

final class SpecialUser{ 
    private $id; 
    private $location; 

    public function __construct(\Location $location,$id=''){ 
     $this->id = $id; 
     $this->location = $location; // $container['embed']['location']; 
} 

を、私たちは私たちのGeneralHelper.phpが成立するだ:

final class Location{ 
    public $lat; 
    public $lng; 
    public function __construct($lat='',$lng=''){ $this->lat = $lat; $this->lng = $lng;} 
} 
final class LocationDetails{ 
    public $id; 
    public $addresss; 
    public function __construct($id='',$address=''){$this->id = $id; $this->address = $address;} 
} 
class GeneralDataType{ 
    public $id; 
    public $name; 
    public function getName(){ return $this->name;} 
    public function getId(){ return $this->id;} 
} 

、私たちは次のようになります私たちの「スペシャルクラス」のコントローラを持っています:

final class SpecialController{ 

    public function foor($some_array){ 
     $this->doSomething($some_array); 
    } 

    private function doSomething($ret_value){ 
     // do something 
     $arr = array(); 

     foreach($ret_value as $key => $value){ 
      $something = $container['embed']['getGeneralDataFromArray']($value); 
      $special_location = $container['embed']['special_location']; 
      $arr[] = special_location; 
     } 
     return $arr; 
    } 
    } 

最後に、私たちは私たちの主な "ドライバ"、main.phpを持って

require('PContainer.php'); 
.... 
... 
$some_array = array(....); 
$special_controller = new SpecialController(); 
$special_controller->foor($some_array); 

問題: 1)ReuseableContainer内にinitOutterClass関数を追加して、「特別な」クラスを切り離す必要がありましたが、どのようにしてより良い方法でそれらを切り離すことができましたか?新しい「特別な」9コンテナなどを作り出していますか?今度はすべてがコンテナの内側に座っています。同じことがinitGlobalFunctions()にも続きます。

2)SpecialHelper.phpに関して:コンストラクタですが、もし私が従属する20のオブジェクトプロパティを持っていれば、コンストラクタのINPUTパラメータとしてそれらをすべて入れなければなりませんか?同じことがSpecialUserクラスに行きますが、もし私が$this->location = $location;の代わりにを作ってDIに依存することができたら$場所があります! :/

3)特別なクラスコントローラに入れたいにもかかわらず、別のファイルにSpecialHelper.phpを作成しなければならなかったので、未知のものはありません)

4)大切なことは、「特殊クラス」コントローラーについてですが、どのようにdoSomethingメソッドを解決するのですか?私は "特別な場所"オブジェクトをループ内に作成する必要がありますが、私はその$コンテナが認識されない(おそらくグローバルであるにもかかわらず、スコープとして)しかしそれ以上のものは本当に依存している!それは私的な関数なので、今から使用するすべてのクラスにコンテナを渡すことは望ましくありません。それは正しいですか?

すべてのヘルプがにappriciatedされて...私が最も重要)

+0

あなたが自分のことをやろうとしている理由は、本当に私には分かりません。私が何かを誤解していない限り、私はおそらく__autoloadとrequire_onceがあなたがしようとしていることを達成するために動作すると思いますか?コンテナオブジェクトをすべてのクラスに渡したくない場合は、静的にすることを検討してください。 – Eva

答えて

1

4ありがとう...ベストプラクティスを理解しようとしている:IOCは正しいです。実装が正しく機能していないということは、IoC自体の原則を反映していません。

関数内でグローバル$コンテナを使用する場合は、その関数内でglobalキーワードを使用する必要があります。それがPHPの仕組みです。それを静的にすることは、参照の問題を解決することですが、実際の違いはありません。

IoCコンテナは、呼び出し元の依存関係を解決します。呼び出し元は、呼び出し先の内部について何も知る必要はなく、どちらも気にしません。したがって、データの交換が規制される何らかの種類の契約が存在するはずです。そのような状況があれば、あなたはIoCを持っています。

3)この問題はあまりにもあいまいではありますが、実用的な観点からも問題はありません。それは動作しますか?さて、お会いできてよかったです。 :-)

2)IoCの手掛かりは、契約の使用です。 IoCコンテナは、発信者と適切な契約を結ぶためのものです。契約は具体的な被呼者に解決されます。被呼者は、契約書と共にインラインで情報を返す。発信者はその答えを理解します。そのため、このプロセスでの入力と出力が特定の実装とは独立していることが必要です。したがって、20個のオブジェクトプロパティを入力として使用せず、代わりに配列または一般オブジェクトを使用してください。

1)テクニカルフロー(クラス間の関係)と機能フロー(データフロー)が混ざ​​っているという考えがあります。 IoCコンテナは技術フローの目的に役立ち、クラス間の関係における依存関係を最適化します。たとえば、データベースに接続する場合は、常に新しい接続を作成するのではなく、既存の接続を再利用することができます。または、フローの中でいくつかの特殊な機能を使用したい場合は、IoCを使用してください。

関連する問題