Laravel - 我的每个服务容器/自定义类都需要服务提供程序吗?

Edm*_*mas 5 php service dependency-injection inversion-of-control laravel

服务容器/提供者可能比我想象的要简单得多,但经过几个小时的阅读后,我仍然完全没有得到它.

我在其中创建了一个简单的DateFormatapp/Library.在内部创建别名后,\config\app.php我可以立即在任何控制器或刀片模板中使用它.

<?php namespace App\Library;

class DateFormat {

    public static function getDate($timestamp){
      // processing the timestamp      
    }

}
Run Code Online (Sandbox Code Playgroud)

我刚刚创建了一个服务容器吗?如果是,我是否还需要创建服务提供商?哪里有绑定到图片?

我真的很感激这个问题的一些亮点.
谢谢

tpt*_*cat 13

不,你创建的只是你班级的别名.服务提供者是绑定特定类的一种方式,通常与Facade结合使用.

别名只是一种使用类的便捷方式,无需每次都导入整个命名空间类.

例如,如果您有一个类\My\Very\Long\Class\Adapter,则可以在config/app.php以下位置对其进行别名:

// config/app.php
<?php
'aliases' => [
    // a bunch of aliases
    'MyAdapter' => My\Very\Long\Class\Adapter::class,
]
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做:

<?php

new MyAdapter();
... 
Run Code Online (Sandbox Code Playgroud)

代替:

<?php

use My\Very\Long\Class\Adapter;
...
new Adapter();
...
Run Code Online (Sandbox Code Playgroud)

当您想要解决依赖关系时,通常会使用服务提供程序,最常见的是通过注入.当您要解析的类需要将参数传递到构造函数或每次都有一个公共设置时,这会很有用.您可以在提供程序中执行所有设置.

这是一个场景:

您有一个要与之交互的API.我们称之为SuperApi.SuperAPI的文档说,要创建SuperApi类的实例,您必须执行以下操作:

<?php
// Some method (a controller or something)
public function index()
{
    $superApi = new \SuperApi\Connector($key, $secret);
    return $superApi->getCustomers();
}
Run Code Online (Sandbox Code Playgroud)

现在,你要创建的这个实例每次,你就必须做相同的设置(或抽象它的一些类,但事实是,你需要传递一个$key$secret在构造函数).

如果您要为此类创建别名Connector,可能会是:

// config/app.php
<?php
'aliases' => [
    // a bunch of aliases
    'SuperApi' => SuperApi\Connector::class,
]
Run Code Online (Sandbox Code Playgroud)

所以使用该别名,您现在可以执行此操作:

<?php

// Some method (a controller or something)
public function index()
{
    $superApi = new SuperApi($key, $secret);
    return $superApi->getCustomers();
}
Run Code Online (Sandbox Code Playgroud)

但是你看,即使使用了别名,你仍然需要通过$key$secret.

这是服务提供商可以提供帮助的地方.

// app/Providers/SuperApiProvider.php
<?php

namespace App\Providers;

use SuperApi\Connector;
use Illuminate\Support\ServiceProvider;

class SuperApiProvider extends ServiceProvider
{
    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('superApiConnector', function ($app) {
            return new ApiConnector($app['config']->get('super-api.key'), $app['config']->get('super-api.secret'));
        });
    }
}

// app/Providers/SuperApi.php (the Facade)
<?php

namespace App\Providers;

use Illuminate\Support\Facades\Facade;

class SuperApi extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'superApiConnector';
    }
}


// config/super-api.config
<?php

return [
    'key' => env('SUPER_API_KEY'),
    'secret' => env('SUPER_API_SECRET'),
];

// config/app.php
<?php
'providers' => [
    // a bunch of providers
    App\Providers\SuperApiProvider::class,
]
Run Code Online (Sandbox Code Playgroud)

请注意,您在provider('superApiConnector')中绑定的字符串与从Facade返回的字符串相同,而且在这种情况下,Facade的类名是实际调用绑定类的方式SuperApi.

现在,当您想要使用SuperApi\Connector该类时,您可以执行以下操作:

<?php

// Some method (a controller or something)
public function index()
{
    return SuperApi::getCustomers();
}
Run Code Online (Sandbox Code Playgroud)

正如我上面所说,提供商真正派上用场的是当你想要注入它并让Laravel的IoC容器自动解析注入的类:

<?php
// Some method (a controller or something)
public function index(SuperApi $api)
{
    return $api->getCustomers();
}
Run Code Online (Sandbox Code Playgroud)

需要说明的是,您不需要服务提供商来利用依赖注入.只要应用程序可以解析类,就可以注入它.这意味着你注入的类的构造函数需要的任何参数也需要自动解析.