2017-01-07 10 views
2

私はビジネスロジックを実行するサービス層クラスを持っています。PHP - 無限ループを引き起こすサービス層クラスのインスタンス化

私は、ユーザーが管理者かどうか、ユーザーがプロジェクトにアクセスしているかどうか、ユーザーが特定の役割を持っているかどうかなどのユーザー役割関連サービスを実行するクラスがあるとします.は、関連するプロジェクトメンバーを取得のようなもの、プロジェクトの詳細など

UserService 
    $projectService; //class variable 

    hasProjectAccess(){ 
    { 
    ... 
    projectMember = projectService->getProjectMembers(); 
    ... 
    } 

    isUserAdmin(){ 
     return true|false; //just an example 
    } 

ProjectService 
    $userService; //class variable 
    getProjectMembers(){ 
    { 
    ... 
    perform some logic to create array of members 
    ... 
    if(userService.isUserAdmin()) 
     .. perform some other logic 
    ... 
    } 

私はそれがすべての依存関係をインスタンス化して注入するContainerクラスの使用スリム3を、使用しています。

UserServiceクラスをインスタンス化しようとすると、(settersメソッドを使用して)ProjectServiceクラスをインスタンス化する必要があります。これは、UserServiceクラスをインスタンス化する必要があります。...など...無限ループを作成します。 (循環依存性)。

Java/Springのようなものを実現しようとしています。クラス内で必要なサービスが異なり、Springを使用してそれに接続するので、循環依存性について心配する必要はありません。

基本的なことを除いて、私はPHPに慣れていません。

詳細情報が必要な場合はお知らせください。

答えて

0

Pimple Slim3の依存性コンテナとして使用されているJava f.exのSpringほど強力ではありません。単純なコンテナであり、基本的な機能性しかありません。

class A { 
    private $b; 
    public function __construct(B $b) { $this->b = $b; } 
} 
class B { 
    private $a; 
    public function setA(A $a) { $this->a = $a; } 
} 

$container = new \Slim\Container; 
$b = new B; 
$a = new A($b); 
$b->setA($a); 

$container['A'] = function($c) use ($a) { 
    return $a; 
}; 
$container['B'] = function($c) use ($b) { 
    return $b; 
}; 
$aFromContainer = $container['A']; 

私はそれを自動化することが可能となりますスリムコンテナにいくつかの小さな変更を加えました。ただ自分で循環依存関係を持っているあなたは、あなたのオブジェクトを初期化する必要がにきびの機能を使用するときに

このプロセス(これは、私が大プロジェクトでどれくらいうまく行っているかわかりません)

class MyContainer extends \Slim\Container 
     implements \Interop\Container\ContainerInterface { 
    private $resolveStack = []; 
    private $resolveLater = []; 

    /** 
    * @see \Pimple\Container::offsetSet() 
    * 
    * Additionally define objects which will be later set with a method. 
    */ 
    public function resolveLater(string $id, callable $value, array $later) { 
     $this[$id] = $value; 
     foreach($later as $item) { 
      if(!isset($this->resolveLater[$item])) $this->resolveLater[$item] = []; 
      $this->resolveLater[$item][] = $id; 
     } 
    } 

    /** 
    * @see \Pimple\Container::offsetGet() 
    * 
    * Additionally set objects which were previously defined in #resolveLater. 
    */ 
    public function offsetGet($id) { 
     if(isset($this->resolveStack[$id])) { return $this->resolveStack[$id]; } 
     $this->resolveStack[$id] = parent::offsetGet($id); 
     if(isset($this->resolveLater[$id])) { 
      foreach($this->resolveLater[$id] as $item) { 
       $this[$item]->{'set' . $id}($this->resolveStack[$id]); 
      } 
     } 
     return array_pop($this->resolveStack); 
    } 
} 

上記の例:このような

class A { 
    public function setB(B $b) { $this->b = $b; } 
    public function setC(C $c) { $this->c = $c; } 
} 
class B { 
    public function setA(A $a) { $this->a = $a; } 
    public function setC(C $c) { $this->c = $c; } 
} 
class C { 
    public function setA(A $a) { $this->a = $a; } 
    public function setB(B $b) { $this->b = $b; } 
} 
$container = new MyContainer; 
$container->resolveLater('A', function($container) { 
    return new A; 
}, ['B', 'C']); 
$container->resolveLater('B', function($container) { 
    return new B; 
}, ['A', 'C']); 
$container->resolveLater('C', function($container) { 
    return new C; 
}, ['A','B']); 
$a = $container['C']; 
var_dump($a); 

これでしょう出力は何か:

object(C)[20] 
    public 'b' => 
    object(B)[22] 
     public 'a' => 
     object(A)[21] 
      public 'b' => 
      &object(B)[22] 
      public 'c' => 
      &object(C)[20] 
     public 'c' => 
     &object(C)[20] 
    public 'a' => 
    object(A)[21] 
     public 'b' => 
     object(B)[22] 
      public 'a' => 
      &object(A)[21] 
      public 'c' => 
      &object(C)[20] 
     public 'c' => 
     &object(C)[20] 
関連する問題