laravel 入口文件/laravel/public/index.php
1 |
|
Composer 自动加载
composer将通过命名空间/文件目录的形式存储到/laravel/vendor/composer/autoload_classmap.php中,自动加载时通过命名空间寻找类文件,并实现加载
创建app实例
1 |
|
创建应用实例
/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php
1 | public function __construct($basePath = null) |
总体来说app初始化的工作为: 1、设置路径 2、绑定了app对象和packages包的实例 3、注册了基本服务提供者 4、增加了核心类的别名
绑定核心接口到容器
主要的动作为绑定一些重要的接口到容器,以便之后可以直接使用.
此过程中加载中间件,通过bootstrappers数组完成环境监测,配置加载,异常处理,Facades注册,服务提供者注册,启动服务
singleton方法 将传入的类名路径转换为一个启动服务的闭包,并保存在容器的bindings属性中
通过APP容器实例化Kernel类
通过
make
方法解析kernel类1
2
3
4
5
6
7
8
9
10
11
12public function make($abstract, array $parameters = [])
{
//获取之前创建app实例中的别名,这个时候还没有别名,直接返回类路径
$abstract = $this->getAlias($abstract);
//不是延迟加载的服务
if (isset($this->deferredServices[$abstract]) && ! isset($this->instances[$abstract])) {
$this->loadDeferredProvider($abstract);
}
//通过父类make方法解析kernel类
return parent::make($abstract, $parameters);
}父类
make
方法解析1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64public function make($abstract, array $parameters = [])
{
return $this->resolve($abstract, $parameters);
}
protected function resolve($abstract, $parameters = [])
{
$abstract = $this->getAlias($abstract);
//检测上下文绑定,这个属于契约接口的动态调用
$needsContextualBuild = ! empty($parameters) || ! is_null(
$this->getContextualConcrete($abstract)
);
// If an instance of the type is currently being managed as a singleton we'll
// just return an existing instance instead of instantiating new instances
// so the developer can keep using the same objects instance every time.
//instances数组中有该类,并且不需要构建上下文的话,便直接返回该类实例
if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
return $this->instances[$abstract];
}
//将实例化类的参数存入数组
$this->with[] = $parameters;
//获取该类闭包,若无则还是返回类名字符串
$concrete = $this->getConcrete($abstract);
// We're ready to instantiate an instance of the concrete type registered for
// the binding. This will instantiate the types, as well as resolve any of
// its "nested" dependencies recursively until all have gotten resolved.
//如果当前解析的类没有上下文绑定,并且是一个闭包则直接进行构建,否则递归make方法获得该契约绑定的类
if ($this->isBuildable($concrete, $abstract)) {
$object = $this->build($concrete);
} else {
$object = $this->make($concrete);
}
// If we defined any extenders for this type, we'll need to spin through them
// and apply them to the object being built. This allows for the extension
// of services, such as changing configuration or decorating the object.
foreach ($this->getExtenders($abstract) as $extender) {
$object = $extender($object, $this);
}
// If the requested type is registered as a singleton we'll want to cache off
// the instances in "memory" so we can return it later without creating an
// entirely new instance of an object on each subsequent request for it.
//若该类绑定时设置为共享,则缓存至instances单例数组
if ($this->isShared($abstract) && ! $needsContextualBuild) {
$this->instances[$abstract] = $object;
}
$this->fireResolvingCallbacks($abstract, $object);
// Before returning, we will also set the resolved flag to "true" and pop off
// the parameter overrides for this build. After those two things are done
// we will be ready to return back the fully constructed class instance.
$this->resolved[$abstract] = true;
array_pop($this->with);
return $object;
}加载中间件
解析kernel类时,最终会构建在实例化app时绑定的kernel实现(
App\Http\kernel
),通过构造方法加载中间,中间件组,以及路由中间件.
处理请求
解析kernel后,在index.php文件中利用kernel的handle方法,传入了一个request对象,来处理这次的网页url请求。此处是通过使用管道模式进行路由分发,定位到控制器,被response类包装成响应对象返回至index.php,通过send方法发送至浏览器.