Laravel最大的特性之一就是能够创建一个易于扩展、高度自定义的服务。你可以实例化多个遵循某个接口的类,并通过一个管理类来处理它们。例如,你可以在程序中任意调用session守卫、api守卫或是jwt守卫去检索、存储用户的信息。
Manager Class
Illuminate\Support\Manager 是驱动管理的基础。通过继承这个抽象类,我们可以轻松扩展自定义服务,并能够实例化多种不同的驱动。接下来,我们通过第三方登陆的场景来介绍Laravel的类。
假设我们的平台允许多个第三方账号登陆,例如:QQ登陆、微信登陆、Gitee登陆、Google登陆等。每个平台对外开放了不同的接口,不同的方式去获取该平台的用户信息,返回的数据也各不相同。但是,我们的目标只有一个,获取用户第三方的唯一标识、用户昵称和头像等基础信息,然后将其保存,关联到我们自己平台下的唯一账号。
小伙伴们不妨先思考一下,一般我们会怎样实现这一功能...
创建一个LoginManager
如上图所示,LoginManager继承自Manager类,LoginManager依赖于WeChatProvider和GithubProvider。WeChatProvider和GitHubProvider有一个共同的抽象标准ProviderAbstract,用于从第三方平台获取用户的信息。 LoginManager代码如下
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Support\Manager;
use App\Contract\Login\Factory;
class LoginManager extends Manager implements Factory
{
/**
* 创建github登陆的驱动.
*
* @return App\Http\Controllers\Auth\Provider\ProviderAbstract
*/
protected function createGithubDriver()
{
return new GitHubProvider()
}
/**
* 创建微信登陆的驱动.
*
* @return App\Http\Controllers\Auth\Provider\ProviderAbstract
*/
protected function createWeChatDriver()
{
return new WeChatProvider()
}
/**
* 设置默认的驱动.
*
* @return string
*/
public function getDefaultDriver()
{
return 'github';
}
}
在服务容器中绑定Factory
然后,我们在 App\Providers\AppserviceProvider.php中添加如下代码
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->singleton(Factory::class, function ($app) {
return new LoginManager($app);
});
}
}
上述代码中的singleton方法表示Factory在服务容器中只会被实例化一次,之后获取的都是第一次实例化的对象。
之后,我们可以在 App\Providers\AppserviceProvider.php任意扩展LoginManager,当然,也可以在LoginManager中定义其他的驱动。
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function boot()
{
$this->app->make(Factory::class)->extend('google', function ($app) {
return new GoogleProvider($app)
})
$this->app->make(Factory::class)->extend('gitee', function ($app) {
return new GiteeProvider($app)
})
...
}
}
方法的调用
<?php
// 在这里简单举例,建议为LoginManaager写一个Contract或是Facades。使用更简洁的调用方法
$manager = app()->make(Factory::class);
$manager->driver()->login(); // 默认是github
$manager->driver('wechat')->login();
$manager->driver('google')->login();
$manager->driver('gitee')->login();
总结
在这只是简单介绍一下Laravel的Manager设计模式,如果你需要实现某个问题不同的解决方案,这会是一个不错的起点。