国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Laravel 管道流原理

Mr_zhang / 964人閱讀

摘要:管道流原理強(qiáng)烈依賴函數(shù),我們先來了解下函數(shù)的使用。第二次迭代時(shí),的值為上述返回的閉包偽代碼,的值為,返回一個(gè)閉包,當(dāng)我們執(zhí)行這個(gè)閉包時(shí),滿足,得到結(jié)果。自定義中間件為的管道流核心類在的方法中,為上述的閉包,為要通過的中間件數(shù)組,為對(duì)象。

Laravel管道流原理強(qiáng)烈依賴array_reduce函數(shù),我們先來了解下array_reduce函數(shù)的使用。

原標(biāo)題PHP 內(nèi)置函數(shù) array_reduce 在 Laravel 中的使用

array_reduce

在看array_reducelaravel中的應(yīng)用時(shí),先來看看array_reduce官方文檔是怎么說的。

array_reduce() 將回調(diào)函數(shù) callback 迭代地作用到 array 數(shù)組中的每一個(gè)單元中,從而將數(shù)組簡化為單一的值。

mixed array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] )

array

輸入的 array。

callback

mixed callback ( mixed $carry , mixed $item )
$carry包括上次迭代的值,如果本次迭代是第一次,那么這個(gè)值是 initialitem 攜帶了本次迭代的值

initial

如果指定了可選參數(shù) initial,該參數(shù)將在處理開始前使用,或者當(dāng)處理結(jié)束,數(shù)組為空時(shí)的最后一個(gè)結(jié)果。

從文檔說明可以看出,array_reduce函數(shù)是把數(shù)組的每一項(xiàng),都通過給定的callback函數(shù),來簡化的。

那我們就來看看是怎么簡化的。

$arr = ["AAAA", "BBBB", "CCCC"];

$res = array_reduce($arr, function($carry, $item){
    return $carry . $item;
});

給定的數(shù)組長度為3,故總迭代三次。

第一次迭代時(shí) $carry = null $item = AAAA 返回AAAA

第一次迭代時(shí) $carry = AAAA $item = BBBB 返回AAAABBBB

第一次迭代時(shí) $carry = AAAABBBB $item = CCCC 返回AAAABBBBCCCC

這種方式將數(shù)組簡化為一串字符串AAAABBBBCCCC

帶初始值的情況
$arr = ["AAAA", "BBBB", "CCCC"];

$res = array_reduce($arr, function($carry, $item){
    return $carry . $item;
}, "INITIAL-");

第一次迭代時(shí)($carry = INITIAL-),($item = AAAA) 返回INITIAL-AAAA

第一次迭代時(shí)($carry = INITIAL-AAAA),($item = BBBB), 返回INITIAL-AAAABBBB

第一次迭代時(shí)($carry = INITIAL-AAAABBBB),($item = CCCC),返回INITIAL-AAAABBBBCCCC

這種方式將數(shù)組簡化為一串字符串INITIAL-AAAABBBBCCCC

閉包
$arr = ["AAAA", "BBBB", "CCCC"];

//沒帶初始值
$res = array_reduce($arr, function($carry, $item){
    return function() use ($item){//這里只use了item
        return strtolower($item) . "-";
    };
});

第一次迭代時(shí),$carry:null,$item = AAAA,返回一個(gè)use了$item = AAAA的閉包

第二次迭代時(shí),$carry:use了$item = AAAA的閉包,$item = BBBB,返回一個(gè)use了$item = BBBB的閉包

第一次迭代時(shí),$carry:use了$item = BBBB的閉包,$item = CCCC,返回一個(gè)use了$item = CCCC的閉包

這種方式將數(shù)組簡化為一個(gè)閉包,即最后返回的閉包,當(dāng)我們執(zhí)行這個(gè)閉包時(shí)$res()得到返回值CCCC-

上面這種方式只use ($item),每次迭代返回的閉包在下次迭代時(shí),我們都沒有用起來。只是又重新返回了一個(gè)use了當(dāng)前item值的閉包。

閉包USE閉包
$arr = ["AAAA"];

$res = array_reduce($arr, function($carry, $item){
    return function () use ($carry, $item) {
        if (is_null($carry)) {
            return "Carry IS NULL" . $item;
        }
    };
});

注意,此時(shí)的數(shù)組長度為1,并且沒有指定初始值

由于數(shù)組長度為1,故只迭代一次,返回一個(gè)閉包 use($carry = null, $item = "AAAA"),當(dāng)我們執(zhí)行($res())這個(gè)閉包時(shí),得到的結(jié)果為Carry IS NULLAAAA

接下來我們重新改造下,

$arr = ["AAAA", "BBBB"];

$res = array_reduce($arr, function($carry, $item){
    return function () use ($carry, $item) {
        if (is_null($carry)) {
            return "Carry IS NULL" . $item;
        }
        if ($carry instanceof Closure) {
            return $carry() . $item;
        }
    };
});

我們新增了一個(gè)條件判斷,若當(dāng)前迭代的值是一個(gè)閉包,返回該閉包的執(zhí)行結(jié)果。

第一次迭代時(shí),$carry的值為null$item的值為AAAA,返回一個(gè)閉包,

//偽代碼
function () use ($carry = null, $item = AAAA) {
    if (is_null($carry)) {
        return "Carry IS NULL" . $item;
    }
    if ($carry instanceof Closure) {
        return $carry() . $item;
    }
}

假設(shè)我們直接執(zhí)行該閉包,將會(huì)返回Carry IS NULLAAAA的結(jié)果。

第二次迭代時(shí),$carry的值為上述返回的閉包(偽代碼),$item的值為BBBB,返回一個(gè)閉包,

當(dāng)我們執(zhí)行這個(gè)閉包時(shí),滿足$carry instanceof Closure,得到結(jié)果Carry IS NULLAAAABBBB

Laravel中的array_reverse

大致了解了array_reverse函數(shù)的使用后,我們來瞅瞅laravel管道流里使用array_reverse的情況。

我在Laravel中間件原理中有闡述,強(qiáng)烈建議先去看看Laravel中間件原理再回過頭來接著看。

php內(nèi)置方法array_reduce把所有要通過的中間件都通過callback方法并壓縮為一個(gè)Closure。最后在執(zhí)行Initial

Laravel中通過全局中間件的核心代碼如下:

//IlluminateFoundationHttpKernel.php
protected function sendRequestThroughRouter($request)
{
    return (new Pipeline($this->app))
        ->send($request)
        ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
        ->then($this->dispatchToRouter());
}
protected function dispatchToRouter()
{
    return function ($request) {
        $this->app->instance("request", $request);
        return $this->router->dispatch($request);
    };
}

正如我前面說的,我們發(fā)送一個(gè)$request對(duì)象通過middleware中間件數(shù)組,最后在執(zhí)行dispatchToRouter方法。

假設(shè)有兩個(gè)全局中間件,我們來看看這兩個(gè)中間件是如何通過管道壓縮為一個(gè)Closure的。

IlluminateFoundationHttpMiddlewareCheckForMaintenanceMode::class,
AppHttpMiddlewareAllowOrigin::class,//自定義中間件

IlluminatePipelinePipeline為laravel的管道流核心類.

IlluminatePipelinePipelinethen方法中,$destination為上述的dispatchToRouter閉包,pipes為要通過的中間件數(shù)組,passableRequest對(duì)象。

public function then(Closure $destination)
{
    $pipeline = array_reduce(
        array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
    );
    return $pipeline($this->passable);
}

array_reverse函數(shù)將中間件數(shù)組的每一項(xiàng)都通過$this->carry(),初始值為上述dispatchToRouter方法返回的閉包。

protected function prepareDestination(Closure $destination)
{
    return function ($passable) use ($destination) {
        return $destination($passable);
    };
}
protected function carry()
{
    return function ($stack, $pipe) {
        return function ($passable) use ($stack, $pipe) {
            if ($pipe instanceof Closure) {
                return $pipe($passable, $stack);
            } elseif (! is_object($pipe)) {
                //解析中間件參數(shù)
                list($name, $parameters) = $this->parsePipeString($pipe);
                $pipe = $this->getContainer()->make($name);
                $parameters = array_merge([$passable, $stack], $parameters);
            } else {
                $parameters = [$passable, $stack];
            }
            return $pipe->{$this->method}(...$parameters);
        };
    };
}

第一次迭代時(shí),返回一個(gè)閉包,use$stack$pipe$stack的值為初始值閉包,$pipe為中間件類名,此處是AppHttpMiddlewareAllowOrigin::class(注意array_reverse函數(shù)把傳進(jìn)來的中間件數(shù)組倒敘了)。

假設(shè)我們直接運(yùn)行該閉包,由于此時(shí)$pipe是一個(gè)String類型的中間件類名,只滿足! is_object($pipe)這個(gè)條件,我們將直接從容器中make一個(gè)該中間件的實(shí)列出來,在執(zhí)行該中間件實(shí)列的handle方法(默認(rèn)$this->methodhandle)。并且將request對(duì)象和初始值作為參數(shù),傳給這個(gè)中間件。

public function handle($request, Closure $next)
{
    //......
}

在這個(gè)中間件的handle方法中,當(dāng)我們直接執(zhí)行return $next($request)時(shí),相當(dāng)于我們開始執(zhí)行array_reduce函數(shù)的初始值閉包了,即上述的dispatchToRouter方法返回的閉包。

protected function dispatchToRouter()
{
    return function ($request) {
        $this->app->instance("request", $request);
        return $this->router->dispatch($request);
    };
}

好,假設(shè)結(jié)束。在第二次迭代時(shí),也返回一個(gè)use$stack$pipe$stack的值為我們第一次迭代時(shí)返回的閉包,$pipe為中間件類名,此處是IlluminateFoundationHttpMiddlewareCheckForMaintenanceMode::class

兩次迭代結(jié)束,回到then方法中,我們手動(dòng)執(zhí)行了第二次迭代返回的閉包。

return $pipeline($this->passable);

當(dāng)執(zhí)行第二次迭代返回的閉包時(shí),當(dāng)前閉包use$pipeIlluminateFoundationHttpMiddlewareCheckForMaintenanceMode::class,同樣只滿足! is_object($pipe)這個(gè)條件,我們將會(huì)從容器中makeCheckForMaintenanceMode中間件的實(shí)列,在執(zhí)行該實(shí)列的handle方法,并且把第一次迭代返回的閉包作為參數(shù)傳到handle方法中。

當(dāng)我們?cè)?b>CheckForMaintenanceMode中間件的handle方法中執(zhí)行return $next($request)時(shí),此時(shí)的$next為我們第一次迭代返回的閉包,將回到我們剛才假設(shè)的流程那樣。從容器中make一個(gè)AppHttpMiddlewareAllowOrigin實(shí)列,在執(zhí)行該實(shí)列的handle方法,并把初始值閉包作為參數(shù)傳到AllowOrigin中間件的handle方法中。當(dāng)我們?cè)僭?b>AllowOrigin中間件中執(zhí)行return $next($request)時(shí),代表我們所有中間件都通過完成了,接下來開始執(zhí)行dispatchToRouter

中間件是區(qū)分先后順序的,從這里你應(yīng)該能明白為什么要把中間件用array_reverse倒敘了。

并不是所有中間件在運(yùn)行前都已經(jīng)實(shí)例化了的,用到的時(shí)候才去想容器取

中間件不執(zhí)行$next($request)后續(xù)所有中間件無法執(zhí)行。

這篇文章是專們?yōu)榱松弦黄狶aravel中間件原理寫的,因?yàn)樵趯慙aravel中間件原理時(shí)我也不很清楚array_reducelaravel中的運(yùn)行流程。如果有什么不對(duì)的,歡迎指正。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/23190.html

相關(guān)文章

  • Laravel中間件原理

    摘要:直到所有中間件都執(zhí)行完畢,最后在執(zhí)行最后的即上述的方法如果上述有地方難懂的,可以參考這邊文章內(nèi)置函數(shù)在中的使用以上是在通過全局中間件時(shí)的大致流程,通過中間件和路由中間件也是一樣的,都是采用管道流操作,詳情可翻閱源碼 簡介 Laravel 中間件提供了一種方便的機(jī)制來過濾進(jìn)入應(yīng)用的 HTTP 請(qǐng)求, 如ValidatePostSize用來驗(yàn)證POST請(qǐng)求體大小、ThrottleReque...

    張憲坤 評(píng)論0 收藏0
  • 深入理解 Laravel 管道

    摘要:將請(qǐng)求傳入到指定的中間件路由。用于處理任務(wù)的方法接收兩個(gè)參數(shù),第一個(gè)是一個(gè)可傳遞的對(duì)象,第二個(gè)是閉包,在運(yùn)行最后一個(gè)管道后對(duì)象將被重定向到這個(gè)閉包。我希望這個(gè)實(shí)例能夠讓你對(duì)有更深如的了解,并知道如何使用它們。 這是一篇譯文,原文 Understanding Laravel Pipelines。譯文首發(fā)于 深入理解 Laravel 管道,轉(zhuǎn)載請(qǐng)注明出處。 基本上,你可以使用 larave...

    paraller 評(píng)論0 收藏0
  • laravel框架學(xué)習(xí)--中間件middleware

    摘要:好久沒有寫文章了,記錄一下這段時(shí)間學(xué)習(xí)的東西吧中間件是個(gè)非常方便的東西,能將一些邏輯實(shí)現(xiàn)解耦,并且在中,中間件的編寫也是非常的方便。對(duì)于的中間件,他的實(shí)現(xiàn)原理也是和這個(gè)一樣的。 好久沒有寫文章了,記錄一下這段時(shí)間學(xué)習(xí)的東西吧 laravel中間件是個(gè)非常方便的東西,能將一些邏輯實(shí)現(xiàn)解耦,并且在laravel中, 中間件的編寫也是非常的方便。誰用誰知道。 1.裝飾器模式 laravel中...

    Pandaaa 評(píng)論0 收藏0
  • laravel框架應(yīng)用和composer擴(kuò)展包開發(fā)

    摘要:官方地址是目前最流行的框架,發(fā)展勢(shì)頭迅猛,應(yīng)用非常廣泛,有豐富的擴(kuò)展包可以應(yīng)付你能想到的各種應(yīng)用場(chǎng)景,框架思想前衛(wèi),跟隨時(shí)代潮流,提倡優(yōu)雅代碼,自稱為工匠,其中的模板引擎容器以及擴(kuò)展包為業(yè)務(wù)的開發(fā)提供了極大的便利。 laravel5.5+ laravel官方地址 laravel是目前最流行的php框架,發(fā)展勢(shì)頭迅猛,應(yīng)用非常廣泛,有豐富的擴(kuò)展包可以應(yīng)付你能想到的各種應(yīng)用場(chǎng)景,lara...

    shevy 評(píng)論0 收藏0
  • php管道模式手測(cè)

    摘要:所以管道模式大致需要三個(gè)角色管道,閥門和載荷流水。模仿返回處理后的結(jié)果輸出結(jié)語上面的代碼并沒有達(dá)到中間件的真正執(zhí)行部分,例子中只是用到了管道模式的一部分。 一直在用Laravel框架,很喜歡laravel框架的中間件。在請(qǐng)求到結(jié)果之前,如果我們想要對(duì)路由或請(qǐng)求進(jìn)行額外的處理,簡單的加個(gè)Midleware中間件就行了,很簡單,很方便是不是。最近幾天看了下它的中間件的實(shí)現(xiàn)方式,把自己的心得...

    zzir 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<