“系统架构”的版本间的差异
(→Facades) |
(→Facade与助手函数) |
||
(未显示同一用户的2个中间版本) | |||
第95行: | 第95行: | ||
相反的,Cache facade继承了基底Facade类以及定义了getFacadeAccessor()方法。记住,这个方法的工作是返回服务容器绑定的名称。当用户在Cache facade上参考任何的静态方法,Laravel会从服务容器解析被绑定的cache以及针对对象运行请求的方法(在这个例子中是get)。 | 相反的,Cache facade继承了基底Facade类以及定义了getFacadeAccessor()方法。记住,这个方法的工作是返回服务容器绑定的名称。当用户在Cache facade上参考任何的静态方法,Laravel会从服务容器解析被绑定的cache以及针对对象运行请求的方法(在这个例子中是get)。 | ||
+ | |||
+ | ===Facade简化调用的例子=== | ||
+ | |||
+ | 我们使用一个Laravel中的例子,来说明一下Facade是如何简化调用的。我们需要调用设置数据缓存的方法,使用Facade的语法如下: | ||
+ | |||
+ | <source lang='php'> | ||
+ | use Illuminate\Support\Facades\Cache; | ||
+ | |||
+ | Route::get('/cache', function() { | ||
+ | |||
+ | // 事先保证执行下面的put方法,将缓存存入 | ||
+ | // Cache::put('key', 'HelloKang', 10); | ||
+ | |||
+ | // 获取缓存项key的内容 | ||
+ | return Cache::get('key'); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | 如果不使用Facade来调用,那么调用的语法如下: | ||
+ | |||
+ | <source lang='php'> | ||
+ | Route::get('/cache', function() { | ||
+ | // 获取缓存项key的内容 | ||
+ | return app('cache')->get('key'); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | |||
+ | ===Facade与助手函数=== | ||
+ | |||
+ | 类似于简化语法的操作,除了使用Facade来实现外,Laravel还提供了函数语法,称之为助手函数,helper。其目的都是一致的,就是简化调用语法。 | ||
+ | |||
+ | Cache::get('key') 这个语法可以更简单的由 cache('key') 来实现。是不是语法更简单了呢。 | ||
+ | |||
+ | 其实这两个语法的本质是一样的,我们可以观察 cache() 函数的实现: | ||
+ | |||
+ | 定义:/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php | ||
+ | |||
+ | <source lang="php"> | ||
+ | function cache() | ||
+ | { | ||
+ | $arguments = func_get_args(); | ||
+ | |||
+ | // 如果只有一个参数,则解析出cache服务,完成get操作 | ||
+ | if (is_string($arguments[0])) { | ||
+ | return app('cache')->get($arguments[0], isset($arguments[1]) ? $arguments[1] : null); | ||
+ | } | ||
+ | |||
+ | // 其他代码略... | ||
+ | |||
+ | // 如果只有两个参数,则解析出cache服务,完成set操作 | ||
+ | return app('cache')->put(key($arguments[0]), reset($arguments[0]), $arguments[1]); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | 可以看出来,cache这个助手函数,也是完成解析服务,调用方法操作的工作。与Facade是一致的! | ||
+ | |||
+ | 那么疑问来了:是不是功能重复了?我们该选择使用Facade还是Helper? | ||
+ | |||
+ | 是重复了,但是对于Cache来说,仅仅重复了put和get这两个操作。 | ||
+ | |||
+ | 助手函数,通常仅仅实现了最最常用的服务功能。而Facede就是直接解析出来服务,调用启发方法,换句话说,就是提供完善的服务功能。 | ||
+ | |||
+ | ===总结=== | ||
+ | |||
+ | * Facade,就是访问服务方法的快捷语法,不同我们从服务容器中手动解析,直接调用封装好的Facade即可完成任务。 | ||
+ | * 其语法实现是利用PHP类的静态方法重载来实现的。 | ||
+ | * 更加快捷的语法是助手函数,但是助手函数不能提供完善的服务功能,仅仅是最常用的功能,很多时候还是要使用Facade。 | ||
==Contracts== | ==Contracts== |
2017年10月24日 (二) 02:28的最后版本
请求生命周期
require __DIR__.'/../bootstrap/autoload.php'; $app = require_once __DIR__.'/../bootstrap/app.php'; //创建服务容器 /** * 创建http核心(或者终端核心)。 * config/app.php * 1、注册服务提供者 * 2、boot() * 3、注册中间件 */ $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); /** * 1、路由分派 * 2、执行路由中间件 * 3、跳转到控制器 */ $response = $kernel->handle( $request = Illuminate\Http\Request::capture() ); $response->send(); $kernel->terminate($request, $response);
应用程序结构
服务提供者
服务提供者是所有Laravel应用程序启动的中心所在。包括你自己的应用程序,以及所有的Laravel核心服务,都是通过服务提供者启动的。
若你打开Laravel的config/app.php文件,你将会看到providers数组。这些都是你的应用程序会加载到的所有服务提供者类。当然,它们之中有很多属于「延迟」提供者,意味着除非真正需要它们所提供的服务,否则它们并不会在每一个请求中都被加载。
- 注册方法
如同之前提到的,在register方法中,你应该只将事物绑定至服务容器中。永远不要尝试在register方法中注册任何事件侦听器、路由或任何其它功能。否则的话,你可能会意外地使用到由尚未加载的服务提供者所提供的服务。
- 延迟提供者
若你的提供者仅在服务容器中注册绑定,你可以选择延缓其注册,直到真正需要其中已注册的绑定,延迟提供者加载可提高应用程序的性能。
要延迟提供者加载,可将defer属性设置为true,并定义一个provides方法。provides方法会返回提供者所注册的服务容器绑定。
服务容器
在服务提供者中,你总是可以通过$this->app实例变量访问容器。
- 绑定
- 绑定一个单例
- 绑定实例
- 绑定接口至实现
- 情境绑定
- 标记
- 解析
有几种方式可以从容器中解析一些东西。
$fooBar = $this->app->make('FooBar');
或者,你可以像数组一样从容器中进行访问,因为他实现了PHP的ArrayAccess接口:
$fooBar = $this->app['FooBar'];
- 容器事件
每当服务容器解析一个对象时就会触发事件。你可以使用resolving方法监听这个事件。
Facades
Facades为应用程序的服务容器中可用的类提供了一个「静态」接口。Laravel本身附带许多的facades,甚至你可能在不知情的状况下已经在使用他们!Laravel「facades」作为在服务容器内基类的「静态代理」,拥有简洁、易表达的语法优点,同时维持着比传统静态方法更高的可测试性和灵活性。
$user = Cache::get('user:'.$id);
如果我们查看Illuminate\Support\Facades\Cache类,你会发现没有静态方法get。
相反的,Cache facade继承了基底Facade类以及定义了getFacadeAccessor()方法。记住,这个方法的工作是返回服务容器绑定的名称。当用户在Cache facade上参考任何的静态方法,Laravel会从服务容器解析被绑定的cache以及针对对象运行请求的方法(在这个例子中是get)。
Facade简化调用的例子
我们使用一个Laravel中的例子,来说明一下Facade是如何简化调用的。我们需要调用设置数据缓存的方法,使用Facade的语法如下:
use Illuminate\Support\Facades\Cache; Route::get('/cache', function() { // 事先保证执行下面的put方法,将缓存存入 // Cache::put('key', 'HelloKang', 10); // 获取缓存项key的内容 return Cache::get('key'); }
如果不使用Facade来调用,那么调用的语法如下:
Route::get('/cache', function() { // 获取缓存项key的内容 return app('cache')->get('key'); }
Facade与助手函数
类似于简化语法的操作,除了使用Facade来实现外,Laravel还提供了函数语法,称之为助手函数,helper。其目的都是一致的,就是简化调用语法。
Cache::get('key') 这个语法可以更简单的由 cache('key') 来实现。是不是语法更简单了呢。
其实这两个语法的本质是一样的,我们可以观察 cache() 函数的实现:
定义:/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php
function cache() { $arguments = func_get_args(); // 如果只有一个参数,则解析出cache服务,完成get操作 if (is_string($arguments[0])) { return app('cache')->get($arguments[0], isset($arguments[1]) ? $arguments[1] : null); } // 其他代码略... // 如果只有两个参数,则解析出cache服务,完成set操作 return app('cache')->put(key($arguments[0]), reset($arguments[0]), $arguments[1]); }
可以看出来,cache这个助手函数,也是完成解析服务,调用方法操作的工作。与Facade是一致的!
那么疑问来了:是不是功能重复了?我们该选择使用Facade还是Helper?
是重复了,但是对于Cache来说,仅仅重复了put和get这两个操作。
助手函数,通常仅仅实现了最最常用的服务功能。而Facede就是直接解析出来服务,调用启发方法,换句话说,就是提供完善的服务功能。
总结
- Facade,就是访问服务方法的快捷语法,不同我们从服务容器中手动解析,直接调用封装好的Facade即可完成任务。
- 其语法实现是利用PHP类的静态方法重载来实现的。
- 更加快捷的语法是助手函数,但是助手函数不能提供完善的服务功能,仅仅是最常用的功能,很多时候还是要使用Facade。
Contracts
Laravel的Contracts是一组定义了框架核心服务的接口(php class interfaces)。例如:
- Illuminate\Contracts\Queue\Queue contract 定义了队列任务所需要的方法
- Illuminate\Contracts\Mail\Mailer contract 定义了寄送e-mail需要的方法
框架对于每个contract都有提供对应的实现。
- Contracts Vs. Facades
Laravel的facades提供一个简单的方法来使用服务,而不需要使用类型提示和在服务容器之外解析contracts。然而,使用contracts可以明显地定义出类的依赖,对大部分应用进程而言,使用facade就足够了,然而,若你实在需要特别的低耦合,使用contracts可以做到这一点。
- 简单性
当所有的Laravel服务都使用简洁的接口定义,就能够很容易决定一个服务需要提供的功能。可以将contracts视为说明框架特色的简洁文档。
除此之外,当依赖的接口足够简洁时,代码的可读性和可维护性大大提高。比起搜索一个大型复杂的类里有哪些可用的方法,你有一个简单,干净的接口可以参考。