在Laravel中创建Service Provider和Facade

环境

Laravel 5.4

前言

下面我们以“音乐播放器”为例子,介绍如何在Laravel中创建一个Service Provider,并且为这个Provider创建一个门面(Facade)。

创建自定义Service Provider

1)既然是音乐播放器,那肯定会有播放功能,因此先定义一个音乐播放器的接口,接口有一个play方法,文件路径app/Helpers/Contracts/MusicPlayerContract.php:

namespace App\Helpers\Contracts;

interface MusicPlayerContract
{
    public function play();
}

2)然后创建一个QQ音乐播放器类,并实现上述接口,文件路径app/Helpers/QQPlayer.php:

namespace App\Helpers;

use App\Helpers\Contracts\MusicPlayerContract;

class QQPlayer implements MusicPlayerContract
{
    public function play()
    {
        echo '开始播放QQ音乐';
    }
}

再创建一个酷狗音乐播放器类:

namespace App\Helpers;

use App\Helpers\Contracts\MusicPlayerContract;

class KugouPlayer implements MusicPlayerContract
{

    public function play()
    {
        echo '开始播放酷狗音乐';
    }
}

3)然后我们创建一个Service Provider,将这个音乐播放服务以单例的方式绑定到Laravel的容器中,绑定的service_id为player,文件路径app/Providers/MusicPlayerServiceProvider.php:

namespace App\Providers;

use App\Helpers\Contracts\MusicPlayerContract;
use App\Helpers\QQPlayer;
use Illuminate\Support\ServiceProvider;

class MusicPlayerServiceProvider extends ServiceProvider
{

    protected $defer = true; // 延迟加载

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('player', function() {
            return new QQPlayer();
        });
        // 因为有两个播放器,将接口和播放器绑定起来,这样依赖注入接口时,容器就会知道应该实例化哪个播放器
        $this->app->bind(MusicPlayerContract::class, QQPlayer::class);
    }

    /**
     * 延迟加载时必须定义此方法
     * @return string[]
     */
    public function provides()
    {
        return ['player'];
    }

}

4)修改config/app.php配置文件,将上面的Provider添加到providers数组里:

'providers' => [
        /*
         * 省略的其它Service Provider...
         */
        App\Providers\MusicPlayerServiceProvider::class,

    ],

5)至此,Service Provider已经创建完毕。在Controller中我们可以通过容器的make方法、或resolve辅助函数、或者依赖注入来调用音乐播放服务:

namespace App\Http\Controllers;

use App\Helpers\Contracts\MusicPlayerContract;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\App;

class Controller extends BaseController
{
    // 普通模式
    public function test()
    {
        $service = App::make('player'); // 方式一
        //$service = resolve('player'); // 方式二
        $service->play();
    }

    // 依赖注入模式
    public function test2(MusicPlayerContract $player)
    {
        $player->play();
    }
}

创建Facade

上面我们创建的Service Provider,每次调用都需要通过容器的make方法,或者resolve辅助函数来获取服务对象,不是很方便,我们可以通过创建一个门面(Facade)类来解决这个问题。

1)创建一个Player门面类,文件路径app/Facades/Player.php:

namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class Player extends Facade
{
    protected static function getFacadeAccessor() {
        return 'player';
    }
}

在门面类中,需要重写父类的getFacadeAccessor方法,在方法中需返回Service Provider与Laravel容器之间绑定的service_id,在此例子中是player。

2)然后我们就可以通过Facade的静态调用接口直接使用音乐播放服务了:

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;
use App\Facades\Player; // 导入Facade类

class Controller extends BaseController
{
    public function test()
    {
        Player::play(); // 直接静态调用,无需实例化对象
    }
}

3)如上面代码所示,在使用Facade类的时候,需要先通过use关键字把Facade类导入进来。如果我们把Facade类添加到config/app.php配置文件中的aliases数组中,就可以把导入的步骤也省了:

'aliases' => [
		/* 省略的其它别名... */
        'Player' => App\Facades\Player::class,
    ],

4)配置好alias别名后的调用示例,无需再导入Facade类:

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;

class Controller extends BaseController
{
    public function test()
    {
        \Player::play(); // 注意在Player前有一个 \ 反斜杠
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值