laravel 学习笔记2

2017-09-13 10:27:05来源:oschina作者:aalphaa人点击

分享

问:要把大象装进冰箱,总共分几步?


答:三步。第一步,把冰箱门打开;第二步,把大象装进去;第三步,把冰箱门关上。


问:要写一个web框架,总共分几步?


laravel答:三步。第一步,接收一个请求;第二步,处理这个请求;第三步,返回一个响应。


以上就是《laravel学习笔记》系列的第一集全部剧情回顾。没看过的同学,到这里看。


相信大家都看到了,laravel就这副揍性。太能装了,对吧?没关系,看它能装多久。咱这回就看看他到底怎么“处理”的请求。直奔主题,揭开丫的面具。


$response = $kernel->handle(
$request = Illuminate/Http/Request::capture()
);

就是这句。直接看handle方法。


有同学就问了,上一句$kernel怎么来的?是个什么东西?都还不知道呢?不知道就不知道呗。我现在也不知道,它就是个http"核",就知道这么多。不管什么来头,咱就看它怎么handle的。


同学又说了,咋这么能吹呢?不知道咋来的,对应代码在哪呢?找不到handle的代码看毛啊。


呃,好像没毛病。看来还得老老实实看下上一句


$kernel = $app->make(Illuminate/Contracts/Http/Kernel::class);

“核”是主角“做”出来的。


主角app 在根目录下bootstrap/app.php里


$app = new Illuminate/Foundation/Application(
realpath(__DIR__.'/../')
);

顺藤摸瓜,到 Illuminate/Foundation/Application 里瞅瞅,这个甩手掌柜,怎么“做”的?


对应的文件是 vendor/laravel/framework/src/Illuminate/Foundation/Application.php,别问我怎么知道的。自动加载不是我要说的。


public function make($abstract, array $parameters = [])
{
$abstract = $this->getAlias($abstract);
if (isset($this->deferredServices[$abstract])) {
$this->loadDeferredProvider($abstract);
}
return parent::make($abstract, $parameters);
}

看起来好像不复杂,抓重点,咱的目标是找"核"的handle对应代码,别走丢了。看最后一句return,这家伙原来是坑爹货,自己不会,喊他爹“做”,行,无视它了,看看他爹是谁?


class Application extends Container implements ApplicationContract, HttpKernelInterface

哦,他爹叫Container"容器",怪不得laravel的文档上来就先灌输“容器”概念。容器,这下找到laravel为啥能装的根了,祖上就有这个“装”的基因啊。任你装,咱就一根筋,就看他到底怎么“做”?


vendor/laravel/framework/src/Illuminate/Container/Container.php文件的make方法


public function make($abstract, array $parameters = [])
{
$abstract = $this->getAlias($this->normalize($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.
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
$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.
if ($this->isBuildable($concrete, $abstract)) {
$object = $this->build($concrete, $parameters);
} else {
$object = $this->make($concrete, $parameters);
}
// 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.
if ($this->isShared($abstract)) {
$this->instances[$abstract] = $object;
}
$this->fireResolvingCallbacks($abstract, $object);
$this->resolved[$abstract] = true;
return $object;
}

擦,有种掉坑里的强烈感觉。“做”法看起来很复杂的样子。


咱跑这里来是为了看"核"怎么做出来的,然后才能知道“核”到底怎么“处理”。


有点慌乱啊,怎么就走丢了呢?心理想起一个声音“help,I‘m lost”。


索性,歇会。喝口水,收拾下心情。回想下,事情哪里不对了?app这个坑爹货,叫他爹做的时候,他爹怎么就知道要做什么呢?对,回头检查下,原来是要做Illuminate/Contracts/Http/Kernel::class样的“核”。


看下 /vendor/laravel/framework/src/Illuminate/Contracts/Http/Kernel.php 就是个接口,没有具体实现。Contracts这个叫“契约”的,也是官方文档强行灌输的概念之一。好么~容器,契约 都出现了。


原来契约就是接口啊,也对,接口就是约定,叫契约没毛病啊,这完全符合laravel一贯很装的调调。


还是不对啊,你爹只根据一个接口,就能做一个具体的“核”来?打死你我也不信。


哎,还是再看看$app这个既坑爹,又当甩手掌柜的家伙吧。


/bootstrap/app.php 文件


$app->singleton(
Illuminate/Contracts/Http/Kernel::class,
App/Http/Kernel::class
);

这就对了,看来是之前太轻视这家伙了。这货应该是先把App/Http/Kernel::class 和 Illuminate/Contracts/Http/Kernel::class 关联了。不然他爹能耐再大也不行啊。


打开app/Http/Kernel.php 看下,又一个坑爹货,里面一堆一堆的middleware“中间件”属性。“中间件”在官方文档里也有专门介绍。继续,找他爹Illuminate/Foundation/Http/Kernel


在文件 vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php


public function handle($request)
{
try {
$request->enableHttpMethodParameterOverride();
$response = $this->sendRequestThroughRouter($request);
} catch (Exception $e) {
$this->reportException($e);
$response = $this->renderException($request, $e);
} catch (Throwable $e) {
$this->reportException($e = new FatalThrowableError($e));
$response = $this->renderException($request, $e);
}
$this->app['events']->fire('kernel.handled', [$request, $response]);
return $response;
}

终于揪出来了,让哥插会腰,得瑟下下。


放眼望去,关键就特么一句啊:


$response = $this->sendRequestThroughRouter($request);

都是些不好好办事的主,相互推诿,自己干的都是些鸡毛蒜皮,无关痛痒。(貌似这符合神马职责单一的设计原则),管它呢,咱的重点就是揭露真相。


继续看


protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
$this->bootstrap();
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}

很明显,关键就是return这句。这个Pipeline的“管道”很有意思。这集就到这里结束了,下集重点玩弄下这个管状物,哈哈。


这集差点还栽了,好险。官方文档提到的 容器、契约、中间件 咱都碰到了。但是这里不深究,后面会一个个扒皮抽筋,当街曝晒,不着急。

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台