一、Laravel框架运行机制(一)全局基本加载逻辑流程-php
这是Laravel框架的入口文件,pubic/index.php的代码,很简单,分了四个部分:
//加载laravel框架的autoload机制
require __DIR__.'/../bootstrap/autoload.php';
//取得app实例
$app = require_once __DIR__.'/../bootstrap/app.php';
//执行app,生成输出内容
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
//输出
$response->send();
$kernel->terminate($request, $response);
首先加载larave根目录下bootstrap驱动里的autoload.php;这个文件引用后就是部署好对整个vendor的自动加载机制。实现后面根据命名名空间自动调用到vendor里的对应类。
然后执行取得app:Illuminate\Foundation\Application的实例;对APP的初始化。
然后生成$kernel,传入的是Illuminate\Contracts\Http\Kernel,但经过laravel的容器处理,生成的是App\Http\Kernel的核心处理类实例,laravel的容器Container维护着一套绑定关系bindings;在类文件Illuminate\Container\Container的$bindings属性值:下是 Illuminate\Container\Container对传来的Illuminate\Contracts\Http\Kernel的判断:
而bindings的值里即存在对应的concrete值,这里就是laravel里到处可见的闭包函数的使用,如下图:
所以传入Illuminate\Contracts\Http\Kernel后,最后返回实例化的App\Http\Kernel对象,实例化App\Http\Kernel的时又去查laravel的ClassMap如下图:
最后就调到了应用目录下的app/Http/Kernel,而此类继承自类:use Illuminate\Foundation\Http\Kernel as HttpKernel;HttpKernel 里的handle方法对路由进行分析、处理请求并返回Pipeline类的处理结果,实际是 Illuminate\Http\Response类的实例化对象。
上面的这步$request = Illuminate\Http\Request::capture(),是分析请求的所有参数,包括get/post/cookies以及server数据等。这步就是响应的核心,即传入所有入参,执行请求处理。
程序执行到第三步,此时实际页面已经响应输出内容了,但laravel框架不知道是怎么回事,后面才执行$response->send();,而$response->send();这句代码是输出了很多header参数,我不认为这是laravel有意这样做,因为这看起来很无语。
$response->send();一看就是要响应输出,然而laravel框架把这句和后面的那句代码注释掉,页面已经响应输出结果了。按这句话的本意逻辑,前面的handle只是处理请求,并不输出,要输出的结果已经入response对象了,再调用$response->send();输出。
最后的这句$kernel->terminate($request, $response);对一些中间件进行了再处理。未再细看,laravel里的很多对象都特别特别地大,打印出来后根本没法看。第一篇就写这么多。
二、Php使用数组索引的方式访问对象-ArrayAccess(数组式访问)接口
如果你没有接触过对象的数组式访问,你肯定不会想到对象也可以使用数组的方式来访问(对象不被转化成数组),因为类和对象是PHP里的两个类型,我们已经习惯了使用->访问对象,而使用索引[]来访问数组。于是对于一个对象,我们能说这样访问呢?如下:
//php数组式访问对象
class Testobj
{
public $testUnit = '-first';
}
$test = new Testobj();
echo $test['testUnit'];
上面的代码肯定会报一个致命错误:Fatal error: Uncaught Error: Cannot use object of type Testobj as array in D:\Htdocs\phpinfo.php on line 9
但是PHP里确实可以实现使用数组的方式来访问对象。PHP自带有一个ArrayAccess(数组式访问)接口,所有的对象只要实现这个接口就可以使用数组的方式来访问对象,
interface ArrayAccess {
abstract public boolean offsetExists ( mixed $offset )
abstract public mixed offsetGet ( mixed $offset )
abstract public void offsetSet ( mixed $offset , mixed $value )
abstract public void offsetUnset ( mixed $offset )
}
ArrayAccess有四个方法,因此实现它的类必须重写这四个方法,如下PHP代码:
//php数组式访问对象
class Test implements ArrayAccess
{
public $testUnit = '-first';
public function getUnit()
{
return 'testunit';
}
public function offsetExists ($offset)
{
echo 1,__METHOD__;
}
public function offsetGet ($offset)
{
echo 2,__METHOD__." ";
if(isset($this->$offset)) return $this->$offset;
elseif(method_exists($this, $offset)) return $this->$offset();
else return ' not found';
}
public function offsetSet ($offset, $value)
{
echo 3,__METHOD__;
}
public function offsetUnset ($offset)
{
echo 4,__METHOD__;
}
}
$test = new Test();
echo $test['testUnit'].'<br>';
echo $test['getUnit'];
类Test继承了ArrayAccess,并且重写了必须重写的4个方法,于是在使用数组式访问对象的时候就会自动去调用offsetGet($key)方法。于是我们能看到下面的输出结果,这种方式实际有点似曾相识的感觉,因为它和我们常见的__set和__get的很相似,只是__set和__get都是在属性找不到时再去进行的操作,而数组式访问是只要是使用数组访问就会调用offset这一系列的方法。上面的只是示例,更好的组织是在类中定义一个数组属性,然后所有的offset系列方法都操作这个数组里的值。
2Test::offsetGet -first
2Test::offsetGet testunit