大家好,我正在创建一个包,我试图在我的类上实现依赖注入,但没有成功。我遵循了所有的指示来做它的工作。我对此感到疯狂。 当我试着打电话
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
}
}
但我可以将接口传递给构造函数并返回接口的函数组,因为接口就像一个契约,所以它可以信任存在该函数。但问题是我无法找到在构造函数上传递该接口的方法。
答案 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?。