laraval 启动:
fpm下
laravel默认读取的uri是$_SERVER[‘REQUEST_URI’];
所以你可以在任何页面构建一个请求test
$uri = '/test';
$_SERVER['REQUEST_URI'] = $uri . '?' . $_SERVER['QUERY_STRING'];
require __DIR__ . '/public/index.php';
运行请求
$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
$kernel->terminate($request, $response);
bootstrap/app.php
//http请求内核
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
//错误控制
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
//这里你可以注册自己的中间件
/**
* 分配中间件到路由
*/
$app->routeMiddleware([
'sign' => App\Http\Middleware\SignMiddleware::class,
]);
//加载路由
$app->group(['namespace' => 'App\Http\Controllers'], function ($app) {
require __DIR__ . '/../app/Http/routes.php';
});
//配置加载配置
$app->configure('cache');
运行完bootstrap/app
开始运行fpm的内核
Illuminate\Foundation\Http\Kernel
class Kernel implements KernelContract
{
protected $bootstrappers = [
//检查环境变量,.env的配置会在这个时候加载
'Illuminate\Foundation\Bootstrap\DetectEnvironment',
//加载config/*下的文件,放到config中
'Illuminate\Foundation\Bootstrap\LoadConfiguration',
//注册log类默认采用mongo,没有配置则会定位到logs/laravel.log
'Illuminate\Foundation\Bootstrap\ConfigureLogging',
'Illuminate\Foundation\Bootstrap\HandleExceptions',
//注测config/app.php中alias中所有配置的别名
'Illuminate\Foundation\Bootstrap\RegisterFacades',
//注册providers,并且运行每个register方法
'Illuminate\Foundation\Bootstrap\RegisterProviders',
//运行每个provider的boot方法
'Illuminate\Foundation\Bootstrap\BootProviders',
];
/**
* Create a new HTTP kernel instance.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function __construct(Application $app, Router $router)
{
$this->app = $app;
$this->router = $router;
//构建的时候配置好路由中间件,定位到单个路由的时候会查询运行
foreach ($this->routeMiddleware as $key => $middleware) {
$router->middleware($key, $middleware);
}
}
/**
* Handle an incoming HTTP request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function handle($request)
{
try {
$request->enableHttpMethodParameterOverride();
//运行请求,如果没有运行到这里一定进入了errorhander,错误控制类中
$response = $this->sendRequestThroughRouter($request);
} catch (Exception $e) {
$this->reportException($e);
$response = $this->renderException($request, $e);
} catch (Throwable $e) {
$e = new FatalThrowableError($e);
$this->reportException($e);
$response = $this->renderException($request, $e);
}
$this->app['events']->fire('kernel.handled', [$request, $response]);
return $response;
}
/**
* Send the given request through the middleware / router.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
$this->bootstrap();
//进入管道,运行全局空间件然后,运行路由中间件,最后运行路由对应的controller
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}
进入laravel\framework\src\Illuminate\Pipeline\Pipeline.php
/**
* Run the pipeline with a final destination callback.
*
* @param \Closure $destination
* @return mixed
*/
public function then(Closure $destination)
{
$firstSlice = $this->getInitialSlice($destination);
$pipes = array_reverse($this->pipes);
//这里建立了一个函数栈,循环递归调用函数,最后运行$firstSlice函数
//第一个中间件运行的时候有两个参数,第一个是request请求结果,第二个是下一个中间件的函数
//也就是中间件handle方法中的$next
return call_user_func(
array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable
);
}
/**
* Get a Closure that represents a slice of the application onion.
*
* @return \Closure
*/
protected function getSlice()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
// If the pipe is an instance of a Closure, we will just call it directly but
// otherwise we'll resolve the pipes out of the container and call it with
// the appropriate method and arguments, returning the results back out.
if ($pipe instanceof Closure) {
return call_user_func($pipe, $passable, $stack);
} else {
list($name, $parameters) = $this->parsePipeString($pipe);
return call_user_func_array([$this->container->make($name), $this->method],
array_merge([$passable, $stack], $parameters));
}
};
};
}