Laravel知识整理

为每个tag生成永久的唯一key vendor/laravel/framework/src/Illuminate/Cache/TagSet.php::resetTag
获取tags唯一的命名空间 vendor/laravel/framework/src/Illuminate/Cache/TagSet.php::getNamespace
生成tags唯一命名空间下的某key vendor/laravel/framework/src/Illuminate/Cache/TaggedCache.php::taggedItemKey

框架解读

实例自动注入

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
<?php
//./vendor/laravel/framework/src/Illuminate/Container/Container.php
public function build($concrete, array $parameters = [])
{
// If the concrete type is actually a Closure, we will just execute it and
// hand back the results of the functions, which allows functions to be
// used as resolvers for more fine-tuned resolution of these objects.
//如果传入的$concrete是一个匿名函数,那么仅仅是执行并返回其结果
if ($concrete instanceof Closure) {
return $concrete($this, $parameters);
}
$reflector = new ReflectionClass($concrete);
// If the type is not instantiable, the developer is attempting to resolve
// an abstract type such as an Interface of Abstract Class and there is
// no binding registered for the abstractions so we need to bail out.
//判断$concreate是否可以被实例化,如果不可实例化抛出异常
if (! $reflector->isInstantiable()) {
$message = "Target [$concrete] is not instantiable.";
throw new BindingResolutionContractException($message);
}
//将$concrete插入到build栈中
$this->buildStack[] = $concrete;
//获取$concrete的构造函数
$constructor = $reflector->getConstructor();
// If there are no constructors, that means there are no dependencies then
// we can just resolve the instances of the objects right away, without
// resolving any other types or dependencies out of these containers.
//如果没有构造函数,从build栈中去除$concrete,然后直接new $concrete并返回实例
if (is_null($constructor)) {
array_pop($this->buildStack);
return new $concrete;
}
//获取构造函数的形参信息
$dependencies = $constructor->getParameters();
// Once we have all the constructor's parameters we can create each of the
// dependency instances and then use the reflection instances to make a
// new instance of this class, injecting the created dependencies in.
//如果传入了实参,那么将实参对照形参转化为key的形式
$parameters = $this->keyParametersByArgument(
$dependencies, $parameters
);
//获取构造函数各个依赖对应的实例
$instances = $this->getDependencies(
$dependencies, $parameters
);
//弹出build栈
array_pop($this->buildStack);
//根据参数实例构建并返回对象
return $reflector->newInstanceArgs($instances);
}

FAQ

1.同步提交表单时,需要使用csrf_token()添加token信息,那么ajax传输时怎么办呢

答: 简述(以laravel5.1为例):
在全局csrf中间件的handle方法中,会自动向请求的cookie中添加token(名为XSRF-TOKEN),客户端向服务端发送异步请求时header中带上这个token,服务端自动比对csrf信息

注意: axios默认自动支持CSRF保护。具体表现是在发送请求时检测cookie中是否存在XSRF-TOKEN,有的话就自动添加到header中
image_1ba40v7khbdc8ol1ncm12k71sr59.png-94kB

顺便说一下laravel全局csrf检测的实现
(1)Laravel开启session时生成一个token并存到session中

1
2
3
4
5
6
7
8
9
10
11
12
13
# vendor/laravel/framework/src/Illuminate/Session/Store.php:90
public function start()
{
$this->loadSession();
if (! $this->has('_token')) {
$this->regenerateToken();
}
return $this->started = true;
}

(2)Laravel默认将注册csrf为全局中间件

1
2
3
4
5
6
7
# app/Http/Kernel.php
...
protected $middleware = [
\App\Http\Middleware\VerifyCsrfToken::class,
];

(3)在csrf中间件执行方法handle中校验
先通过isReading判断请求方式,如果请求方式是READ|GET|OPTIONS其中一种,不做CSRF校验
再通过shouldPassThrouth判断当前请求uri在$excep属性数组中,如果不做校验
最后通过tokensMatch判断csrf token值是否与session中值相等,如果相等通过校验,不相等抛出异常
(请求中token获取顺序:_token > header中X-CSRF-TOKEN > header中X-XSRF-TOKEN)

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
# ...Http/Middleware/VerifyCsrfToken.php:47
public function handle($request, Closure $next)
{
if ($this->isReading($request) || $this->shouldPassThrough($request) || $this->tokensMatch($request)) {
return $this->addCookieToResponse($request, $next($request));
}
throw new TokenMismatchException;
}
//向响应中添加cookie信息
protected function addCookieToResponse($request, $response)
{
$config = config('session');
//向cookie中添加XSRF-TOKEN信息
$response->headers->setCookie(
new Cookie(
'XSRF-TOKEN', $request->session()->token(), time() + 60 * 120,
$config['path'], $config['domain'], $config['secure'], false
)
);
return $response;
}
...

资料

From Apprentice To Artisan