注入绑定到服务容器的实例
Injecting an instance bound to the service container
我有一个服务提供者,我想用它来将 class 的实例绑定到服务容器:
namespace App\Providers;
use Eluceo\iCal\Component\Calendar;
use Illuminate\Support\ServiceProvider;
class IcalProvider extends ServiceProvider
{
public function register()
{
$this->app->instance('iCal', function () {
return new Calendar(config('calendar.name'));
});
}
}
据我了解the documentation on binding an instance,这允许我将键 iCal
绑定到服务容器,以便稍后在我的控制器或服务 class 中输入提示 iCal
并且将使用在服务提供者中创建的实例。
所以我创建了一个控制器并尝试键入提示我的实例:
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class CalendarInviteController extends Controller
{
public function download(iCal $ical, $sessionId)
{
dd($ical);
}
}
但是当我这样做时出现错误:
Class App\Http\Controllers\iCal does not exist
有道理,因为它适用于在不存在的控制器命名空间中寻找名为 iCal
的 class。该实例没有 use 语句,因为 iCal
只是一个文本键,所以我试着告诉它查看根命名空间,认为可以修复它:
public function download(\iCal $ical, $sessionId)
我得到错误:
Class iCal does not exist
当我阅读有关 resolving from the service container 的文档部分时,看起来我在控制器中唯一需要做的就是输入提示来获取实例。
我是不是误解了文档?
更新
我还应该提到我确实将我的服务提供商添加到我的 config/app.php
文件中。
此外,当我创建一个接口时,改为将其绑定到服务容器,编辑供应商代码以实现所述接口,并注入该接口而不是它工作,但这需要我编辑供应商代码,而我不这样做'想要。
正如您在 docs 中看到的那样,方法 instance
需要一个键和一个对象实例来在容器中注册。所以,如果你想在容器中注册一个特定的实例,注册应该是:
namespace App\Providers;
use Eluceo\iCal\Component\Calendar;
use Illuminate\Support\ServiceProvider;
class IcalProvider extends ServiceProvider
{
public function register()
{
//register a specific instance of the Calendar class in the container
$this->app->instance('iCal', new Calendar(config('calendar.name') );
}
}
这样您可以通过以下方式取回实例:
$cal = \App::make('iCal');
如果您的目的是在控制器方法中对 class 进行类型提示,并且您想从服务容器中解析之前注册的实例,您可以这样做:
namespace App\Providers;
use Eluceo\iCal\Component\Calendar;
use Illuminate\Support\ServiceProvider;
class IcalProvider extends ServiceProvider
{
public function register()
{
//the key will be 'Eluceo\iCal\Component\Calendar'
$this->app->instance( Calendar::class, new Calendar(config('calendar.name') );
}
}
现在,在您的控制器中:
namespace App\Http\Controllers;
//important: specify the Calendar namespace
use Eluceo\iCal\Component\Calendar;
class CalendarInviteController extends Controller
{
public function download(Calendar $ical, $sessionId)
{
dd($ical);
}
}
这样 Laravel 会看到您想要一个 Calendar
对象,它会尝试从服务容器中获取它,看看是否存在这个键的绑定:(因为这是命名空间您在控制器中指定的 class 个)
Eluceo\iCal\Component\Calendar
绑定存在!由于您已将此密钥绑定到服务提供商中的服务容器,因此 Laravel 将 return 您注册的实例。
在您提供的代码中,您提示了 class iCal
,但 class 不存在,因此 Laravel 无法实例化 class
如果您想将依赖项注入控制器(这很好,值得称赞!),那么您需要一个接口名称来进行类型提示。
通常您会有一个通用接口,然后将该接口绑定到具体实现。所以你可能有一个日历服务接口,它绑定到你的 iCal 实现。像这样:
use Eluceo\iCal\Component\Calendar;
class CalendarServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('App\Services\Calendar', function ($app) {
return new Calendar(config('calendar.name'));
});
}
public function provides()
{
return ['App\Services\Calendar'];
}
}
只要您在 config/app.php 文件中注册您的服务提供商,您现在就可以在 类:
use App\Services\Calendar;
class InvitationController extends Controller
{
protected $calendar;
public function __construct(Calendar $calendar)
{
$this->calendar = $calendar;
}
}
我有一个服务提供者,我想用它来将 class 的实例绑定到服务容器:
namespace App\Providers;
use Eluceo\iCal\Component\Calendar;
use Illuminate\Support\ServiceProvider;
class IcalProvider extends ServiceProvider
{
public function register()
{
$this->app->instance('iCal', function () {
return new Calendar(config('calendar.name'));
});
}
}
据我了解the documentation on binding an instance,这允许我将键 iCal
绑定到服务容器,以便稍后在我的控制器或服务 class 中输入提示 iCal
并且将使用在服务提供者中创建的实例。
所以我创建了一个控制器并尝试键入提示我的实例:
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class CalendarInviteController extends Controller
{
public function download(iCal $ical, $sessionId)
{
dd($ical);
}
}
但是当我这样做时出现错误:
Class App\Http\Controllers\iCal does not exist
有道理,因为它适用于在不存在的控制器命名空间中寻找名为 iCal
的 class。该实例没有 use 语句,因为 iCal
只是一个文本键,所以我试着告诉它查看根命名空间,认为可以修复它:
public function download(\iCal $ical, $sessionId)
我得到错误:
Class iCal does not exist
当我阅读有关 resolving from the service container 的文档部分时,看起来我在控制器中唯一需要做的就是输入提示来获取实例。
我是不是误解了文档?
更新
我还应该提到我确实将我的服务提供商添加到我的 config/app.php
文件中。
此外,当我创建一个接口时,改为将其绑定到服务容器,编辑供应商代码以实现所述接口,并注入该接口而不是它工作,但这需要我编辑供应商代码,而我不这样做'想要。
正如您在 docs 中看到的那样,方法 instance
需要一个键和一个对象实例来在容器中注册。所以,如果你想在容器中注册一个特定的实例,注册应该是:
namespace App\Providers;
use Eluceo\iCal\Component\Calendar;
use Illuminate\Support\ServiceProvider;
class IcalProvider extends ServiceProvider
{
public function register()
{
//register a specific instance of the Calendar class in the container
$this->app->instance('iCal', new Calendar(config('calendar.name') );
}
}
这样您可以通过以下方式取回实例:
$cal = \App::make('iCal');
如果您的目的是在控制器方法中对 class 进行类型提示,并且您想从服务容器中解析之前注册的实例,您可以这样做:
namespace App\Providers;
use Eluceo\iCal\Component\Calendar;
use Illuminate\Support\ServiceProvider;
class IcalProvider extends ServiceProvider
{
public function register()
{
//the key will be 'Eluceo\iCal\Component\Calendar'
$this->app->instance( Calendar::class, new Calendar(config('calendar.name') );
}
}
现在,在您的控制器中:
namespace App\Http\Controllers;
//important: specify the Calendar namespace
use Eluceo\iCal\Component\Calendar;
class CalendarInviteController extends Controller
{
public function download(Calendar $ical, $sessionId)
{
dd($ical);
}
}
这样 Laravel 会看到您想要一个 Calendar
对象,它会尝试从服务容器中获取它,看看是否存在这个键的绑定:(因为这是命名空间您在控制器中指定的 class 个)
Eluceo\iCal\Component\Calendar
绑定存在!由于您已将此密钥绑定到服务提供商中的服务容器,因此 Laravel 将 return 您注册的实例。
在您提供的代码中,您提示了 class iCal
,但 class 不存在,因此 Laravel 无法实例化 class
如果您想将依赖项注入控制器(这很好,值得称赞!),那么您需要一个接口名称来进行类型提示。
通常您会有一个通用接口,然后将该接口绑定到具体实现。所以你可能有一个日历服务接口,它绑定到你的 iCal 实现。像这样:
use Eluceo\iCal\Component\Calendar;
class CalendarServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('App\Services\Calendar', function ($app) {
return new Calendar(config('calendar.name'));
});
}
public function provides()
{
return ['App\Services\Calendar'];
}
}
只要您在 config/app.php 文件中注册您的服务提供商,您现在就可以在 类:
use App\Services\Calendar;
class InvitationController extends Controller
{
protected $calendar;
public function __construct(Calendar $calendar)
{
$this->calendar = $calendar;
}
}