【发布时间】:2014-07-07 15:24:53
【问题描述】:
我在让依赖注入与依赖反转一起工作时遇到问题。我可以在构造函数中调用 App::make,并且依赖倒置工作得很好……只有当我尝试将它注入构造函数时才会出现问题。
ReflectionException Class StationsInterface does not exist
会命中此问题的 uri 将是 .../stats/station/mogreet/6
文件结构:
-app
-controllers
*StatsController
-Dashboard
-Datasync
-Interfaces
*DatasyncInterface
*MogreetDatasyncInterface
-Services
*MogreetDatasync
*BackendServiceProvider
*DatasyncBase
-Repositories
-Interfaces
*CredentialsInterface
*StationsInterface
-Stations
*DbCredentials
*DbStations
*FileCredentials
-Stats
*BackendServiceProvider
*DbRepositoryBase
相关代码块如下:
服务提供者:
<?php namespace Dashboard\Repositories;
use Illuminate\Support\ServiceProvider;
class BackendServiceProvider extends ServiceProvider {
public function register() {
// Service Providers located in Stats directory
$this->app->bind('StatsDailyInterface', 'Dashboard\Repositories\Stats\DbStatsDaily');
//$this->app->bind('StatsMonthlyRepository', 'Dashboard\Repositories\Stats\DbStatsMonthly');
//$this->app->bind('StatsYearlyRepository', 'Dashboard\Repositories\Stats\DbStatsYearly');
// Service Providers located in Stations directory
$this->app->bind('CredentialsInterface', 'Dashboard\Repositories\Stations\FileCredentials');
$this->app->bind('StationsInterface', 'Dashboard\Repositories\Stations\DbStations');
}
}
Controller:请注意,在 this 的构造函数中,我使用的是 App::make 而不是注入依赖项。如果我注入依赖项,我会得到一个类解析错误,就像我在 DatasyncBase 类中所做的那样。
<?php
use Dashboard\ConrollerFacades\Facades\Services;
class StatsController extends BaseController {
/*
|--------------------------------------------------------------------------
| Stats Controller
|--------------------------------------------------------------------------
|
| Pull and display stats for station, market, or corporate views
|
|
|
*/
private $StationModel;
public function __construct() {
$this->StationModel = App::make('StationsInterface');
}
/**
* Pulls stats for an individual station
*
* @param string $service of station
* @param integer $id of station
*
* @return void
*/
public function station( $service, $stationId ) {
$this->Service = $this->serviceSelector($service);
if(!$this->Service) throw new Exception('Unknown Service Selected', 1);
$this->Service->init($stationId);
exit();
}
/**
* Pulls stats for a Market
*
* @param integer $id of market
*
* @return void
*/
public function market( $service, $marketId ) {
$this->Service = $this->serviceSelector($service);
if(!$this->Service) throw new Exception('Unknown Service Selected', 1);
foreach($StationModel->getStationIdsByMarket($marketId) as $station) {
$this->Service->init($station);
}
exit();
}
/**
* Pulls stats for Corporate (all stations)
*
* @return void
*/
public function corporate( $service ) {
$this->Service = $this->serviceSelector($service);
if(!$this->Service) throw new Exception('Unknown Service Selected', 1);
foreach($StationModel->getAllStationIds() as $station) {
$this->Service->init($station);
}
exit();
}
private function serviceSelector($service) {
switch(strtolower($service)) {
case 'brightcove': return App::make('BrightCoveDatasyncInterface'); break;
case 'facebook': return App::make('FacebookDatasyncInterface'); break;
case 'googleanalytics': return App::make('GoogleAnalyticsDatasyncInterface'); break;
case 'liquidcompass': return App::make('LiquidCompassDatasyncInterface'); break;
case 'mogreet': return App::make('MogreetDatasyncInterface'); break;
case 'twitter': return App::make('TwitterDatasyncInterface'); break;
default: return false; break;
}
}
}
这个类的构造函数是发生依赖注入问题的地方。 DatasyncBase:这个类从不直接实例化,它由像 MogreetDatasync 这样的服务类继承。将构造函数移至 MogreetDatasync 类进行测试并不能解决问题。
<?php namespace Dashboard\Datasync;
use Dashboard\Repositories\Interfaces\StationsInterface;
use Dashboard\Repositories\Interfaces\CredentialsInterface;
class DatasyncBase {
protected $Station;
protected $Credentials;
protected $results;
protected $stats;
public function __construct(StationsInterface $Station , CredentialsInterface $Credentials) {
$this->Station = $Station;
$this->Credentials = $Credentials;
$this->stats = array();
}
public function __destruct() {
unset($this->results);
unset($this->stats);
}
public function init() {}
protected function fetch($uri = null, $post_fields = null) {
$cURL = curl_init();
curl_setopt($cURL, CURLOPT_URL, $uri);
curl_setopt($cURL, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($cURL, CURLOPT_POSTFIELDS, $post_fields);
$this->results = curl_exec($cURL);
curl_close($cURL);
}
}
数据同步服务:
<?php namespace Dashboard\Datasync\Services;
use Dashboard\Datasync\DatasyncBase;
use Dashboard\Datasync\Interfaces\MogreetDatasyncInterface;
class MogreetDatasync extends DatasyncBase implements MogreetDatasyncInterface {
public function init($stationId) {}
protected function uri() {}
protected function parse() {}
protected function write() {}
}
【问题讨论】:
-
你在哪里实例化 DatasyncBase 类?如果你想让 laravel 从 IOC 容器中注入依赖项,你是否意识到你必须 App::make() ?
-
DatasyncBase类只是Datasync的一个父类,所以通过MogreetDatasync的继承来实例化。我不知道您必须 App::make() 来注入依赖项,我的大多数示例仅使用绑定。我将开始研究这种方法,但如果你有一个很好的例子/教程,你可以指点我,那将不胜感激。
-
类型提示的自动注入是 Laravel 所做的,而不是 PHP 所做的。您可以从控制器构造函数注入的原因是因为它是使用 Laravel 的 IOC 容器的 build() 方法实例化的。看看那节课,你会更好地理解发生了什么。我什至相信 Laracasts 有一个关于它的截屏视频 :)
-
我正在尝试将依赖倒置与依赖注入一起使用。需要使用 App::make 使得 IOC 容器能够解析绑定。我仍然无法让依赖反转工作。我将更新问题以反映所做的代码更改以及目录结构。
标签: php laravel-4 ioc-container