界面laravel不绑定为什么?

时间:2014-01-23 14:58:58

标签: php dependency-injection laravel-4 ioc-container

大家好,我正在创建一个包,我试图在我的类上实现依赖注入,但没有成功。我遵循了所有的指示来做它的工作。我对此感到疯狂。 当我试着打电话

Player::team_players(2);
它给我一个错误:

  

传递给Team \ Player \ Player :: __ construct()的参数1必须是   Team \ Player \ StatusPlayerInterface的实例,没有给出,调用   C:\ WAMP \ WWW \最美\工作台\队伍\球员的\ src \队伍\播放器\ PlayerServiceProvider.php   在第35行并定义

我创建了我的类Player.php

<?php namespace Team\Player;

use Team\Player\Models\User;
use Team\Player\Models\Team;
use Team\Player\Models\Fighter;
use Team\Player\StatusPlayerInterface;
use DB;

class Player {

  protected $player;

  function __construct(StatusPlayerInterface $player) {
    $this->player = $player;
  } 

  public function team_players($team_id) {
    return $player->team($team_id);
  }
}

StatusPlayerInterface.php

<?php namespace Team\Player;

interface StatusPlayerInterface {

    public function team($team_id); // active - retired - injured by team id

}

Active.php

<?php namespace Team\Player;

use Team\Player\Models\User;
use Team\Player\Models\Team;
use Team\Player\Models\Fighter;

/**
* 
*/
class Active implements StatusPlayerInterface
{

    protected $user;
    protected $team;
    protected $fighter;

    function __construct(User $user,Team $team,Fighter $fighter)
    {
        $this->user = $user;
        $this->team = $team;
        $this->fighter = $fighter;
    }

    public function team($team_id) 
    {
        return $fighters = $this->fighter->with('user')->where('team_id',$team_id)->active()->Confirmed()->get();
    }

}

PlayerServiceProvider.php

public function register()
    {

         $this->app->bind('Team\Player\StatusPlayerInterface','Team\Player\Player'); // bind the interface
         $this->app['player'] = $this->app->share(function($app)
          {
            return new Player; // line 35
          });

         $this->app->booting(function()
        {
          $loader = \Illuminate\Foundation\AliasLoader::getInstance();
          $loader->alias('Player', 'Team\Player\Facades\Player');
        });
    }

修改

我要做的是遵循Jeffrey Way建议遵循的原则。它说 实体应该是可以延期的,但是接近修改。

我还有2个实现StatusPlayerInterface的类,当然只更改了函数团队的查询()

  • 活动//示例
  • 退休
  • 损伤

然后我有主要类播放器,并且方法 team_players 它应该自动调用被调用实例的函数组。这个方法用于不做

class Player {

 ....

  function team_player($team_id,$status) {
      if (is_a($status) == "Active") {
          $fighters = $this->fighter->with('user')->where('team_id',$team_id)->active()->Confirmed()->get();
      } elseif(is_a($status) == "Retired") {
           $fighters = $this->fighter->with('user')->where('team_id',$team_id)->retired()->Confirmed()->get();
      } 
   // ecc
  }

}

但我可以将接口传递给构造函数并返回接口的函数组,因为接口就像一个契约,所以它可以信任存在该函数。但问题是我无法找到在构造函数上传递该接口的方法。

1 个答案:

答案 0 :(得分:4)

这里的构造函数正在等待$玩家:

class Player {

  ...

  function __construct(StatusPlayerInterface $player) {
    $this->player = $player;
  } 

}

所以你的ServiceProvider应该在第35行传递一个:

return new Player; // line 35

我可以看到你试图用IoC为你做这件事:

$this->app->bind('Team\Player\StatusPlayerInterface','Team\Player\Player');

但是你有两个问题,

1)Team\Player\Player不实现Team\Player\StatusPlayerInterface,它必须。但是Active类确实实现了,你不应该使用它吗?

2)我不确定IoC在代码的这一点上是否有效,不得不问Taylor Otwell本人。

但这是你可以做的事情:

public function register()
{
     $this->app['player'] = $this->app->share(function($app)
      {
        return new Player(new Team\Player\Player);

        //// OR

        return new Player(new Team\Player\Active);
      });

     $this->app->booting(function()
    {
      $loader = \Illuminate\Foundation\AliasLoader::getInstance();
      $loader->alias('Player', 'Team\Player\Facades\Player');
    });
}

您的Player类必须实现StatusPlayerInterface:

class Player implements StatusPlayerInterface {

}

但是我不确定它是否应该,所以,看,这些是建议,我不知道你正在做什么与你的包,所以我只是指出我看到的是错的在它上面,好吗?

修改

例如,您构建的Player类已经传递了播放器状态,对吧?但是,如果构造函数(即构建方式)只接收通过ServiceProvider传递的构造函数,您将如何交换不同的状态?在这种情况下,IoC容器将无法帮助您,因为您应该能够实例化具有3种不同状态的相同类:活动,退役和受伤。

您可以创建一个setPlayerStatus()方法,在请求期间更改它,当然,但在我希望您可以看到,在构建整个包之前,您首先要考虑很多关于您的架构的内容然后根据它编写代码,始终记住IoC容器有其边界,并且有一些解决方案无法解决,只是因为它们是您架构上的问题。

编辑2

您并没有真正将接口传递给构造函数。您传递实现该接口的具体类的具体对象。

再次看错误,它说了三件重要的事情

Argument 1 passed to Team\Player\Player::__construct() 

must be an instance of Team\Player\StatusPlayerInterface, 

none given

所以你需要实例化Player

return new Player;

有一些东西:

return new Player(new Active);

真的,这就是你需要的才能让它发挥作用。错误将消失。但是你需要这个包也可以工作,我担心这还不够。

正如我之前所说,如果 IoC可以在这里工作,你怎么能让它在你需要时发送正确的Active,Retired或Injured实现?我看到两个选择:

1)致电

$this->app->bind('Team\Player\StatusPlayerInterface','Team\Player\Active');
$this->app->bind('Team\Player\StatusPlayerInterface','Team\Player\Retired');
$this->app->bind('Team\Player\StatusPlayerInterface','Team\Player\Injured');

每次你需要其中一个,这很糟糕。

2)在开放封闭原则的情况下,更改架构以使您保持在SOLID轨道中。

阅读工厂设计模式,它可能会帮助您使用这种架构。这是一个答案:What is a Factory Design Pattern in PHP?