Laravel 之 Application---实践篇
作为容器使用方法
在《Application理论篇》中介绍过,它作为容器提供了两个主要的功能:
- 注册创建对象的规则,并在需要的时候创建它;
- 提供了类似全局变量存储数据的能力。
它的基本使用步骤是:
- 向容器注册生成对象的规则
- 从容器里面获取对象
注册构建对象的规则
有两种方式向容器注册生成对象的规则
- 指定要类的地址,这种方式有问题问题,如果类的构造函数的参数是基本数据类型的话,容器无法注入这部分数据,会发导致创建失败
-
指定一个闭包函数,具体创建类的逻辑,可以在闭包函数中定义,最终只需要返回创建的对象。
ServiceProvider
中被大量使用。class Car{ protected $name; public function __construct(\Illuminate\Foundation\Application $app, $name) { $this->name = $name; // $app } function __toString() { return (string)$this->name; } } class Something{ } $app = new \Illuminate\Foundation\Application(); // 使用闭包定义创建对象的规则 $app->bind('car',function()use($app){ return new Car($app,'雷克萨斯'); }); // 使用类名的方式 $app->bind('something',Something::class);
共享对象
有些时候,我们在希望在应用程序运行的过程中,对象只被创建一次。
class Car{ protected $name; public function __construct(\Illuminate\Foundation\Application $app, $name) { $this->name = $name; // $app } function __toString() { return (string)$this->name; } } class Something{ } $app = new \Illuminate\Foundation\Application(); // 使用闭包定义创建对象的规则 $app->bind('car',function()use($app){ return new Car($app,'雷克萨斯'.mt_rand(1,100)); }); $app->singleton('car_singleton',function()use($app){ return new Car($app,'雷克萨斯'.mt_rand(1,100)); }); $range = range(1,5); echo "===============car================\r\n"; foreach ($range as $v){ echo $app->make('car')."\r\n";//每次都会创建新的对象 } echo "===============car_singleton================\r\n"; foreach ($range as $v){ echo $app->make('car_singleton')."\r\n";//对象永远只有一个 }
存储数据
一般而言,在应用程序运行的生命周期中,只会存在一个对象。所以可以把全局性质的数据交由它统一保管。
$app = new \Illuminate\Foundation\Application();
$app->instance('data',[1,2,3]);//数据存入容器中
$data = $app->make('data');// 获取容器中存储的数据
提供了应用程序运行需要的基本功能
注册基础的服务
先有鸡还是先有蛋是未解之谜。但是在larval的Application中,它是最先被创建的对象,它自身执行了一些基础服务的构建。
具体包括
- 把Application对象自身放入容器中。
$this->instance('app', $this);
- 注册
EventServiceProvider
服务,事件(events)系统是laravel根基。 - 注册
LogServiceProvider
服务,作为一个成熟的系统,日志(log)必不可少。 -
注册
RoutingServiceProvider
系列服务,请求被转发给具体的处理控制器的规则,就是由这系列服务控制的。提供注册和执行
ServerProdiver
的功能ServerProdiver
(服务提供者)有下面几个特征:- 构造函数有一个Application类型的参数,通常被被保存在它的属性里面
- 必须有一个
register
方法,这个方法通常的作用是向容器里面注册一个类构建规则或者一个值 - 可以有一个
boot
方法,用来执行一些初始化操作
在laravel中所有的独立的功能模块都是以
ServerProdiver
为单位,注入到容器里面的。提供了设置和获取项目基本信息的接口
项目相关的路径信息都被注入到了容器中
$this->instance('path', $this->path()); $this->instance('path.base', $this->basePath()); $this->instance('path.lang', $this->langPath()); $this->instance('path.config', $this->configPath()); $this->instance('path.public', $this->publicPath()); $this->instance('path.storage', $this->storagePath()); $this->instance('path.database', $this->databasePath()); $this->instance('path.resources', $this->resourcePath()); $this->instance('path.bootstrap', $this->bootstrapPath()); // 使用 $configPath = app('path.config');// 获取项目的配置文件所在目录 // .................
自定义扩展功能
在laravel中,组件内部的一些状态都是通过事件的形式曝露出来的。例如在执行引导器(bootstraper)的时候
public function bootstrapWith(array $bootstrappers) { $this->hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) { $this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);// 派发事件,可以监听该事件,执行自定义逻辑 $this->make($bootstrapper)->bootstrap($this); $this['events']->fire('bootstrapped: '.$bootstrapper, [$this]); } }
另外一些操作是通过类似hook的方式进行的,例如
afterLoadingEnvironment(Closure $callback)
加载完环境变量后执行的操作无论是通过event的方式还是通过hook的方式进行扩展,本质上都是向组件注册一个回掉函数,组件在合适的时机执行这个回掉函数。
本作品采用《CC 协议》,转载必须注明作者和本文链接