Facade 入手
Laravel Facade模式实现方式是:所有的Facade(比如Storage)都需要继承虚拟类Facade。虚拟类Facade提供了一个__callStatic方法,来承接所有的方法调用。
该方法提供的作用包括:
- 获取具体Facade对应的实例。子类实现的getFacadeAccessor方法提供
- 调用实例对应方法。__callStatic方法参数提供。
而Storage Facade对应的实例是FilesystemManager
对象,是通过FilesystemServiceProvider
注册到容器里面的。
适配器
Laravel在多处地方使用到适配器,比如 database
, auth
, filesystem
。不同适配器都会对应一个Manager
后缀的管理器,比如FilesystemManager
对应着filesystem
。
管理器主要功能:
- 创建不同的driver
- 注册新driver
- 获取driver
Storage通过调用disk(或drive、cloud对应配置filesystems.cloud),获取(如果不存在创建)对应driver实例。
如果想实现自己的driver,可以通过FilesystemManager
的extend方法,比如你想使用aliyun oss云存储,那么可以
$this->app->make('filesystem')->extend('aliyun', function ($app, array $config) {
// 返回根据config创建的实例即可
});
如果返回的实例实现了League\Flysystem\FilesystemInterface
接口,那么就使用FilesystemAdapter
统一包装一下,如果没有,直接返回driver实例,给调用方。而所谓的包装,大部分作用是为了和laravel本身的调用接口进行统一,做了一层代理转发。如果driver本身实例存在FilesystemAdapter
没有的方法,还是会溯源调用driver方法。
如果想实现自己的driver,那这里的driver对应的不应该是aliyun官方client实例,而应该实现自己的adapter做一层适配。
调用举例
本身存在方法 getTemporaryUrl
- Storage Facade调用disk方法,获取到driver实例
- driver实例满足
FilesystemInterface
,被FilesystemAdapter
包装 FilesystemAdapter
中的方法temporaryUrl
,接受调用- 调用driver本身的
getTemporaryUrl
的方法。
调用driver本身方法
- Storage Facade调用disk方法,获取到driver实例
- driver实例满足
FilesystemInterface
,被FilesystemAdapter
包装 FilesystemAdapter
中的方法__call
,接受调用- 调用driver本身的方法。
总结
Facade找到Manager实例,Manager创建driver,并调用driver对应的方法。Manager同时负责扩展driver,用Adapter包装driver,来统一调用接口。