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)); } }; }; }