Laravel服务提供者

概念和意义

把组件统一管理起来形成一个服务,和业务层分离,业务代码层调用各种服务。
当修改独立服务的底层实现时,不会影响业务层,达到了降低代码耦合,增强代码分层的架构设计。

使用示例

  1. 执行php artisan make:provider RepositoriesServiceProvider创建一个服务提供者。
  2. 在config/app.php的providers数组中增加该服务提供者。
    	...
    	// laravel框架收到请求后,会在引导服务启动时,加载这里的配置文件,并调用服务提供者的方法
    	App\Providers\RepositoriesServiceProvider::class,
    	...
    
  3. 在app目录下创建Repositories文件夹,用于存储服务。
  4. 在上一步创建的Repositories文件夹内,创建一个Interfaces文件夹,用于存储接口类。
  5. 在Interfaces文件夹中创建一个SMS接口类,用于约束SMS类的实现和业务层使用时的抽象。
    <?php
    namespace App\Repositories\Interfaces;
    
    interface SMSInterface {
        public function send(string $string);
    }
    
  6. 在Repositories文件夹中创建一个对SMS接口的实现类。
    <?php
    
    namespace App\Repositories;
    
    use App\Repositories\Interfaces\SMSInterface;
    
    class AliyunSMS implements SMSInterface
    {
        public function send(string $string)
        {
            echo $string;
        }
    }
    
    
  7. 在第一步命令行创建的服务提供者中,把我们上面实现的SMS服务注册到该服务提供者中,作为该服务提供者的一部分 。
    	...
        public function register()
        {
        	// 当该服务底层不用AliyunSMS作为实现时,只需要在这里绑定对应新的实现即可,无需改动业务层。
            $this->app->bind('App\Repositories\Interfaces\SMSInterface', 'App\Repositories\AliyunSMS');
        }
        ...
    
  8. 在控制器中使用
    	use App\Repositories\Interfaces\SMSInterface;
    	...
        public function test(Request $request, SMSInterface $sms)
        {
            $sms->send('test123');
        }
        ...
    

底层是如何加载的?

public/index.php中调用从容器中make出来的kernel类的handle方法中,其中会调用一个bootstrap方法,也就是引导方法。
其中会把Kernel类中的bootstrappers数组变量内预定义的需要启动的服务,全部启动。

Illuminate\Foundation\Http\Kernel:

    protected $bootstrappers = [
        'Illuminate\Foundation\Bootstrap\DetectEnvironment',
        'Illuminate\Foundation\Bootstrap\LoadConfiguration',
        'Illuminate\Foundation\Bootstrap\ConfigureLogging',
        'Illuminate\Foundation\Bootstrap\HandleExceptions',
        'Illuminate\Foundation\Bootstrap\RegisterFacades',
        'Illuminate\Foundation\Bootstrap\RegisterProviders',
        'Illuminate\Foundation\Bootstrap\BootProviders',
    ];

可以看到有很多服务,其中有一个RegisterProviders服务。
该服务内的bootstrap方法中调用了容器类的registerConfiguredProviders方法

Illuminate\Foundation\Application:

    /**
     * Register all of the configured providers.
     *
     * @return void
     */
    public function registerConfiguredProviders()
    {
        $manifestPath = $this->getCachedServicesPath();

        (new ProviderRepository($this, new Filesystem, $manifestPath))
                    ->load($this->config['app.providers']);
    }

可见该方法读取了config/app.php配置文件中的providers数组,然后使用了\Illuminate\Foundation\ProviderRepository类的load方法。
load方法中有一句代码片段:$this->app->register($this->createProvider($provider));

也就是又迭代该的providers数组,使用容器的register方法进行处理,容器的register方法中有一个判断为:

        if (method_exists($provider, 'register')) {
            $provider->register();
        }

如果该服务内存在register方法,则调用该服务的register方法。
也就是调用了我们创建的服务提供者文件的register方法,将服务所需的类绑定注册到了容器中。

发布了116 篇原创文章 · 获赞 12 · 访问量 99万+

猜你喜欢

转载自blog.csdn.net/u012628581/article/details/102013623