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

資訊專欄INFORMATION COLUMN

Laravel學(xué)習(xí)筆記之Middleware源碼解析

_Dreams / 876人閱讀

摘要:學(xué)習(xí)筆記之已經(jīng)聊過使用了來設(shè)計,看源碼發(fā)現(xiàn)其巧妙用了和的一些數(shù)組函數(shù)來設(shè)計。開發(fā)環(huán)境內(nèi)置函數(shù)和看源碼之前,先看下這幾個內(nèi)置函數(shù)的使用。學(xué)習(xí)筆記之實例化源碼解析已經(jīng)聊過的實例化,得到中的變量,即的實例化對象。后面再學(xué)習(xí)下的源碼,到時見。

說明:本文主要學(xué)習(xí)Laravel的Middleware的源碼設(shè)計思想,并將學(xué)習(xí)心得分享出來,希望對別人有所幫助。Laravel學(xué)習(xí)筆記之Decorator Pattern已經(jīng)聊過Laravel使用了Decorator Pattern來設(shè)計Middleware,看Laravel源碼發(fā)現(xiàn)其巧妙用了Closure和PHP的一些數(shù)組函數(shù)來設(shè)計Middleware。

開發(fā)環(huán)境:Laravel5.3 + PHP7 + OS X 10.11

PHP內(nèi)置函數(shù)array_reverse、array_reduce、call_user_func和call_user_func_array

看Laravel源碼之前,先看下這幾個PHP內(nèi)置函數(shù)的使用。首先array_reverse()函數(shù)比較簡單,倒置數(shù)組,看測試代碼:

$pipes = [
    "Pipe1",
    "Pipe2",
    "Pipe3",
    "Pipe4",
    "Pipe5",
    "Pipe6",
];

$pipes = array_reverse($pipes);

var_dump($pipes);

// output
array(6) {
  [0] =>
  string(5) "Pipe6"
  [1] =>
  string(5) "Pipe5"
  [2] =>
  string(5) "Pipe4"
  [3] =>
  string(5) "Pipe3"
  [4] =>
  string(5) "Pipe2"
  [5] =>
  string(5) "Pipe1"
}

array_reduce內(nèi)置函數(shù)主要是用回調(diào)函數(shù)去迭代數(shù)組中每一個值,并且每一次回調(diào)得到的結(jié)果值作為下一次回調(diào)的初始值,最后返回最終迭代的值:

/**
 * @link http://php.net/manual/zh/function.array-reduce.php
 * @param int $v
 * @param int $w
 *
 * @return int
 */
function rsum($v, $w)
{
    $v += $w;
    return $v;
}

$a = [1, 2, 3, 4, 5];
// 10為初始值
$b = array_reduce($a, "rsum", 10);
// 最后輸出 (((((10 + 1) + 2) + 3) + 4) + 5) = 25
echo $b . PHP_EOL; 

call_user_func()是執(zhí)行回調(diào)函數(shù),并可輸入?yún)?shù)作為回調(diào)函數(shù)的參數(shù),看測試代碼:

class TestCallUserFunc
{
    public function index($request)
    {
        echo $request . PHP_EOL;
    }
}   

/**
 * @param $test
 */
function testCallUserFunc($test)
{
    echo $test . PHP_EOL;
}

// [$class, $method]
call_user_func(["TestCallUserFunc", "index"], "pipes"); // 輸出"pipes"

// Closure
call_user_func(function ($passable) {
    echo $passable . PHP_EOL;
}, "pipes"); // 輸出"pipes"

// function
call_user_func("testCallUserFunc" , "pipes"); // 輸出"pipes"

call_user_func_array與call_user_func基本一樣,只不過傳入的參數(shù)是數(shù)組:

class TestCallUserFuncArray
{
    public function index($request)
    {
        echo $request . PHP_EOL;
    }
}

/**
 * @param $test
 */
function testCallUserFuncArray($test)
{
    echo $test . PHP_EOL;
}

// [$class, $method]
call_user_func_array(["TestCallUserFuncArray", "index"], ["pipes"]); // 輸出"pipes"

// Closure
call_user_func_array(function ($passable) {
    echo $passable . PHP_EOL;
}, ["pipes"]); // 輸出"pipes"

// function
call_user_func_array("testCallUserFuncArray" , ["pipes"]); // 輸出"pipes"
Middleware源碼解析

了解了幾個PHP內(nèi)置函數(shù)后再去看下Middleware源碼就比較簡單了。Laravel學(xué)習(xí)筆記之IoC Container實例化源碼解析已經(jīng)聊過Application的實例化,得到index.php中的$app變量,即IlluminateFoundationApplication的實例化對象。然后繼續(xù)看下index.php的源碼:

/**
 * @var AppHttpKernel $kernel
 */
$kernel = $app->make(IlluminateContractsHttpKernel::class);

$response = $kernel->handle(
    $request = IlluminateHttpRequest::capture()
);

$response->send();

$kernel->terminate($request, $response);

首先從容器中解析出Kernel對象,對于AppHttpKernel對象的依賴:IlluminateFoundationApplication和IlluminateRoutingRouter,容器會自動解析。看下Kernel的構(gòu)造函數(shù):

    /**
     * Create a new HTTP kernel instance.
     *
     * @param  IlluminateContractsFoundationApplication  $app
     * @param  IlluminateRoutingRouter  $router
     */
    public function __construct(Application $app, Router $router)
    {
        $this->app    = $app;
        $this->router = $router;

        foreach ($this->middlewareGroups as $key => $middleware) {
            $router->middlewareGroup($key, $middleware);
        }

        foreach ($this->routeMiddleware as $key => $middleware) {
            $router->middleware($key, $middleware);
        }
    }
    
    // IlluminateRoutingRouter內(nèi)的方法
    public function middlewareGroup($name, array $middleware)
    {
        $this->middlewareGroups[$name] = $middleware;

        return $this;
    }
    
    public function middleware($name, $class)
    {
        $this->middleware[$name] = $class;

        return $this;
    }

構(gòu)造函數(shù)初始化了幾個中間件數(shù)組,$middleware[ ], $middlewareGroups[ ]和$routeMiddleware[ ],Laravel5.0的時候記得中間件數(shù)組還沒有分的這么細(xì)。然后就是Request的實例化:

$request = IlluminateHttpRequest::capture()

這個過程以后再聊吧,不管咋樣,得到了IlluminateHttpRequest對象,然后傳入Kernel中:

    /**
     * Handle an incoming HTTP request.
     *
     * @param  IlluminateHttpRequest  $request
     * @return IlluminateHttpResponse
     */
    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;
    }

主要是sendRequestThroughRouter($request)函數(shù)執(zhí)行了轉(zhuǎn)換操作:把IlluminateHttpRequest對象轉(zhuǎn)換成了IlluminateHttpResponse,然后通過Kernel的send()方法發(fā)送給客戶端。同時,順便觸發(fā)了kernel.handled內(nèi)核已處理請求事件。OK,重點關(guān)注下sendRequestThroughRouter($request)方法:

    /**
     * Send the given request through the middleware / router.
     *
     * @param  IlluminateHttpRequest  $request
     * @return IlluminateHttpResponse
     */
    protected function sendRequestThroughRouter($request)
    {
        $this->app->instance("request", $request);

        Facade::clearResolvedInstance("request");

        /* 依次執(zhí)行$bootstrappers中每一個bootstrapper的bootstrap()函數(shù),做了幾件準(zhǔn)備事情:
        1. 環(huán)境檢測
        2. 配置加載
        3. 日志配置
        4. 異常處理
        5. 注冊Facades
        6. 注冊Providers
        7. 啟動服務(wù)
         protected $bootstrappers = [
            "IlluminateFoundationBootstrapDetectEnvironment",
            "IlluminateFoundationBootstrapLoadConfiguration",
            "IlluminateFoundationBootstrapConfigureLogging",
            "IlluminateFoundationBootstrapHandleExceptions",
            "IlluminateFoundationBootstrapRegisterFacades",
            "IlluminateFoundationBootstrapRegisterProviders",
            "IlluminateFoundationBootstrapBootProviders",
        ];*/
        $this->bootstrap();

        return (new Pipeline($this->app))
                    ->send($request)
                    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                    ->then($this->dispatchToRouter());
    }

$this->bootstrap()主要是做了程序初始化工作,以后再聊具體細(xì)節(jié)。然后是Pipeline來傳輸Request,Laravel中把Pipeline管道多帶帶拿出來作為一個service(可看Illuminate/Pipeline文件夾),說明Pipeline做的事情還是很重要的:主要就是作為Request的傳輸管道,依次通過$middlewares[ ], 或middlewareGroups[ ], 或$routeMiddleware[ ]這些中間件的前置操作,和控制器的某個action或者直接閉包處理得到Response,然后又帶著Reponse依次通過$middlewares[ ], 或middlewareGroups[ ], 或$routeMiddleware[ ]這些中間件的后置操作得到準(zhǔn)備就緒的Response,然后通過send()發(fā)送給客戶端。
這個過程有點像汽車工廠的生產(chǎn)一樣,Pipeline是傳送帶,起初Request可能就是個汽車空殼子,經(jīng)過傳送帶旁邊的一個個機(jī)械手middleware@before的過濾和操作(如檢查零件剛度是不是合格,殼子尺寸是不是符合要求,給殼子噴個漆或抹個油啥的),然后進(jìn)入中央控制區(qū)加個發(fā)動機(jī)(Controller@action ,或Closure),然后又繼續(xù)經(jīng)過檢查和附加操作middleware@after(如添加個擋風(fēng)鏡啥的),然后通過門外等著的火車直接運(yùn)送到消費(fèi)者手里send()。在每一步裝配過程中,都需要Service來支持,Service是通過Container來解析{make()}提供的,并且Service是通過ServiceProvider注冊綁定{bind(),singleton(),instance()}到Container中的。

看下Pipeline的send()和through()源碼:

    public function send($passable)
    {
        $this->passable = $passable;

        return $this;
    }
    
    public function through($pipes)
    {
        $this->pipes = is_array($pipes) ? $pipes : func_get_args();

        return $this;
    }

send()傳送的對象是Request,through()所要通過的對象是$middleware[ ],OK,再看下dispatchToRouter()的源碼直接返回一個Closure:

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

            return $this->router->dispatch($request);
        };
    }

然后重點看下then()函數(shù)源碼:

    public function then(Closure $destination)
    {
        $firstSlice = $this->getInitialSlice($destination);

        $pipes = array_reverse($this->pipes);

        // $this->passable = Request對象
        return call_user_func(
            array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable
        );
    }
    
    protected function getInitialSlice(Closure $destination)
    {
        return function ($passable) use ($destination) {
            return call_user_func($destination, $passable);
        };
    }

這里假設(shè)$middlewares為(盡管源碼中$middlewares只有一個CheckForMaintenanceMode::class):

$middlewares = [
    CheckForMaintenanceMode::class,
    AddQueuedCookiesToResponse::class,
    StartSession::class,
    ShareErrorsFromSession::class,
    VerifyCsrfToken::class,
];

先獲得第一個slice(這里作者是比作"洋蔥",一層層的穿過,從一側(cè)穿過到另一側(cè),比喻倒也形象)并作為array_reduce()的初始值,就像上文中array_reduce()測試?yán)又械?0這個初始值,這個初始值現(xiàn)在是個閉包:

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

$firstSlice = function ($passable) use ($destination) {
    return call_user_func($destination, $passable);
};

OK,然后要對$middlewares[ ]進(jìn)行翻轉(zhuǎn),為啥要翻轉(zhuǎn)呢?
看過這篇Laravel學(xué)習(xí)筆記之Decorator Pattern文章就會發(fā)現(xiàn),在Client類利用Decorator Pattern進(jìn)行依次裝飾的時候,是按照$middlewares[ ]數(shù)組中值倒著new的:

    public function wrapDecorator(IMiddleware $decorator)
    {
        $decorator = new VerifyCsrfToken($decorator);
        $decorator = new ShareErrorsFromSession($decorator);
        $decorator = new StartSession($decorator);
        $decorator = new AddQueuedCookiesToResponse($decorator);
        $response  = new CheckForMaintenanceMode($decorator);

        return $response;
    }

這樣才能得到一個符合$middlewares[ ]順序的$response對象:

$response = new CheckForMaintenanceMode(
                new AddQueuedCookiesToResponse(
                    new StartSession(
                        new ShareErrorsFromSession(
                            new VerifyCsrfToken(
                                new Request()
                        )
                    )
                )
            )
        );

看下array_reduce()中的迭代回調(diào)函數(shù)getSlice(){這個迭代回調(diào)函數(shù)比作剝洋蔥時獲取每一層洋蔥slice,初始值是$firstSlice}:

    protected function getSlice()
    {
        return function ($stack, $pipe) {
            return function ($passable) use ($stack, $pipe) {
                if ($pipe instanceof Closure) {
                    return call_user_func($pipe, $passable, $stack);
                } elseif (! is_object($pipe)) {
                    list($name, $parameters) = $this->parsePipeString($pipe);
                    $pipe = $this->container->make($name);
                    $parameters = array_merge([$passable, $stack], $parameters);
                } else{
                    $parameters = [$passable, $stack];
                }

                return call_user_func_array([$pipe, $this->method], $parameters);
            };
        };
    }

返回的是個閉包,仔細(xì)看下第二層閉包里的邏輯,這里$middlewares[ ]傳入的是每一個中間件的名字,然后通過容器解析出每一個中間件對象:

$pipe = $this->container->make($name);

并最后用call_user_func_array([$class, $method], array $parameters)來調(diào)用這個$class里的$method方法,參數(shù)是$parameters。

Demo

接下來寫個demo看下整個流程。
先簡化下getSlice()函數(shù),這里就默認(rèn)$pipe傳入的是類名稱(整個demo中所有class都在同一個文件內(nèi)):

// PipelineTest.php

// Get the slice in every step.
function getSlice()
{
    return function ($stack, $pipe) {
        return function ($passable) use ($stack, $pipe) {
            /**
             * @var Middleware $pipe
             */
            return call_user_func_array([$pipe, "handle"], [$passable, $stack]);
        };
    };
}

再把$middlewares[ ]中五個中間件類寫上,對于前置操作和后置操作做個簡化,直接echo字符串:

// PipelineTest.php


給上完整的一個Pipeline類,這里的Pipeline對Laravel中的Pipeline做了稍微簡化,只選了幾個重要的函數(shù):

// PipelineTest.php

class Pipeline 
{
    /**
     * @var array
     */
    protected $middlewares = [];

    /**
     * @var int
     */
    protected $request;

    // Get the initial slice
    function getInitialSlice(Closure $destination)
    {
        return function ($passable) use ($destination) {
            return call_user_func($destination, $passable);
        };
    }
    
    // Get the slice in every step.
    function getSlice()
    {
        return function ($stack, $pipe) {
            return function ($passable) use ($stack, $pipe) {
                /**
                 * @var Middleware $pipe
                 */
                return call_user_func_array([$pipe, "handle"], [$passable, $stack]);
            };
        };
    }
    
    // When process the Closure, send it as parameters. Here, input an int number.
    function send(int $request)
    {
        $this->request = $request;
        return $this;
    }

    // Get the middlewares array.
    function through(array $middlewares)
    {
        $this->middlewares = $middlewares;
        return $this;
    }
    
    // Run the Filters.
    function then(Closure $destination)
    {
        $firstSlice = $this->getInitialSlice($destination);
    
        $pipes = array_reverse($this->middlewares);
        
        $run = array_reduce($pipes, $this->getSlice(), $firstSlice);
    
        return call_user_func($run, $this->request);
    }
}

OK,現(xiàn)在開始傳入Request,這里簡化為一個整數(shù)而不是Request對象了:

// PipelineTest.php

/**
 * @return Closure
 */
function dispatchToRouter()
{
    return function ($request) {
        echo $request . ": Send Request to the Kernel, and Return Response." . PHP_EOL;
    };
}

$request = 10;

$middlewares = [
    CheckForMaintenanceMode::class,
    AddQueuedCookiesToResponse::class,
    StartSession::class,
    ShareErrorsFromSession::class,
    VerifyCsrfToken::class,
];

(new Pipeline())->send($request)->through($middlewares)->then(dispatchToRouter());

執(zhí)行php PipelineTest.php得到Response:

10: Check if the application is in the maintenance status.
10: Start session of this request.
10: Verify csrf token when post request.
10: Send Request to the Kernel, and Return Response.
10: Share the errors variable from response to the views.
10: Close session of this response.
10: Add queued cookies to the response.

一步一步分析下執(zhí)行過程:

1.首先獲取$firstSlice

$destination = function ($request) {
    echo $request . ": Send Request to the Kernel, and Return Response." . PHP_EOL;
};
$firstSlice = function ($passable) use ($destination) {
    return call_user_func($destination, $passable);
};

這時經(jīng)過初始化后:

$this->request = 10;
$pipes = [
    VerifyCsrfToken::class,
    ShareErrorsFromSession::class,
    StartSession::class,
    AddQueuedCookiesToResponse::class,
    CheckForMaintenanceMode::class,
];

2.執(zhí)行第一次getSlice()后的結(jié)果作為新的$stack,其值為:

$stack   = $firstSlice;
$pipe    = VerifyCsrfToken::class;
$stack_1 = function ($passable) use ($stack, $pipe) {
        /**
        * @var Middleware $pipe
        */            
    return call_user_func_array([$pipe, "handle"], [$passable, $stack]);
};

3.執(zhí)行第二次getSlice()后的結(jié)果作為新的$stack,其值為:

$stack   = $stack_1;
$pipe    = ShareErrorsFromSession::class;
$stack_2 = function ($passable) use ($stack, $pipe) {
        /**
        * @var Middleware $pipe
        */            
    return call_user_func_array([$pipe, "handle"], [$passable, $stack]);
};

4.執(zhí)行第三次getSlice()后的結(jié)果作為新的$stack,其值為:

$stack   = $stack_2;
$pipe    = StartSession::class;
$stack_3 = function ($passable) use ($stack, $pipe) {
        /**
        * @var Middleware $pipe
        */            
    return call_user_func_array([$pipe, "handle"], [$passable, $stack]);
};

5.執(zhí)行第四次getSlice()后的結(jié)果作為新的$stack,其值為:

$stack   = $stack_3;
$pipe    = AddQueuedCookiesToResponse::class;
$stack_4 = function ($passable) use ($stack, $pipe) {
        /**
        * @var Middleware $pipe
        */            
    return call_user_func_array([$pipe, "handle"], [$passable, $stack]);
};

6.執(zhí)行第五次getSlice()后的結(jié)果作為新的$stack,其值為:

$stack   = $stack_4;
$pipe    = CheckForMaintenanceMode::class;
$stack_5 = function ($passable) use ($stack, $pipe) {
        /**
        * @var Middleware $pipe
        */            
    return call_user_func_array([$pipe, "handle"], [$passable, $stack]);
};

這時,$stack_5也就是then()里的$run,然后執(zhí)行call_user_func($run, 10),看執(zhí)行過程:

1.$stack_5(10) = CheckForMaintenanceMode::handle(10, $stack_4)

echo "10: Check if the application is in the maintenance status." . PHP_EOL;
stack_4(10);

2.$stack_4(10) = AddQueuedCookiesToResponse::handle(10, $stack_3)

$stack_3(10);
echo "10: Add queued cookies to the response." . PHP_EOL;

3.$stack_3(10) = StartSession::handle(10, $stack_2)

echo "10: Start session of this request." . PHP_EOL;
$stack_2(10);
echo "10: Close session of this response." . PHP_EOL;

4.$stack_2(10) = ShareErrorsFromSession::handle(10, $stack_1)

$stack_1(10);
echo "10: Share the errors variable from response to the views." . PHP_EOL;

5.$stack_1(10) = VerifyCsrfToken::handle(10, $firstSlice)

echo "10: Verify csrf token when post request." . PHP_EOL;
$firstSlice(10);

6.$firstSlice(10) =

$firstSlice(10) = call_user_func($destination, 10) = echo "10: Send Request to the Kernel, and Return Response." . PHP_EOL;

OK,再把上面執(zhí)行順序整理一下:

1. echo "10: Check if the application is in the maintenance status." . PHP_EOL; // 第一個step

3_1. echo "10: Start session of this request." . PHP_EOL; // 第三個step

5. echo "10: Verify csrf token when post request." . PHP_EOL; // 第五個step

6.echo "10: Send Request to the Kernel, and Return Response." . PHP_EOL; //第六個step

4. echo "10: Share the errors variable from response to the views." . PHP_EOL; // 第四個step

3_2. echo "10: Close session of this response." . PHP_EOL; // 第三個step

2. echo "10: Add queued cookies to the response." . PHP_EOL; // 第二個step

經(jīng)過上面的一步步分析,就能很清楚Laravel源碼中Middleware的執(zhí)行步驟了。再復(fù)雜的步驟只要一步步拆解,就很清晰每一步的邏輯,然后把步驟組裝,就能知道全貌了。

總結(jié):本文主要學(xué)習(xí)了Laravel的Middleware的源碼,學(xué)習(xí)完后就知道沒有什么神秘之處,只需要動手一步步拆解就行。后面再學(xué)習(xí)下Container的源碼,到時見。

歡迎關(guān)注Laravel-China。

RightCapital招聘Laravel DevOps

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

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

相關(guān)文章

  • Laravel學(xué)習(xí)筆記bootstrap源碼解析

    摘要:總結(jié)本文主要學(xué)習(xí)了啟動時做的七步準(zhǔn)備工作環(huán)境檢測配置加載日志配置異常處理注冊注冊啟動。 說明:Laravel在把Request通過管道Pipeline送入中間件Middleware和路由Router之前,還做了程序的啟動Bootstrap工作,本文主要學(xué)習(xí)相關(guān)源碼,看看Laravel啟動程序做了哪些具體工作,并將個人的研究心得分享出來,希望對別人有所幫助。Laravel在入口index...

    xiaoxiaozi 評論0 收藏0
  • Laravel學(xué)習(xí)筆記Session源碼解析(上)

    摘要:然后中間件使用方法來啟動獲取實例,使用類來管理主要分為兩步獲取實例,主要步驟是通過該實例從存儲介質(zhì)中讀取該次請求所需要的數(shù)據(jù),主要步驟是。 說明:本文主要通過學(xué)習(xí)Laravel的session源碼學(xué)習(xí)Laravel是如何設(shè)計session的,將自己的學(xué)習(xí)心得分享出來,希望對別人有所幫助。Laravel在web middleware中定義了session中間件IlluminateSess...

    NervosNetwork 評論0 收藏0
  • Laravel學(xué)習(xí)筆記Filesystem源碼解析(下)

    摘要:源碼解析這個類的源碼主要就是文件的操作和文件屬性的操作,而具體的操作是通過每一個實現(xiàn)的,看其構(gòu)造函數(shù)看以上代碼知道對于操作,實際上是通過的實例來實現(xiàn)的。可以看下的使用上文已經(jīng)說了,使得對各種的操作變得更方便了,不管是還是得。 說明:本文主要學(xué)習(xí)下LeagueFlysystem這個Filesystem Abstract Layer,學(xué)習(xí)下這個package的設(shè)計思想和編碼技巧,把自己的一...

    Luosunce 評論0 收藏0
  • Laravel學(xué)習(xí)筆記Decorator Pattern

    摘要:把和拼接在一起的場所是,所以需要造一個類,在其內(nèi)部實現(xiàn)對的操作中實現(xiàn)了把原有的進(jìn)過個的裝飾后得到的新的,新的還是的實現(xiàn),還是原來的物種。 說明:Laravel中Middleware的實現(xiàn)主要利用了Decorator Pattern的設(shè)計,本文主要先學(xué)習(xí)下Decorator Pattern如何實現(xiàn),為后面學(xué)習(xí)Middleware的設(shè)計做個鋪墊。Decorator Pattern和Adap...

    dendoink 評論0 收藏0
  • Laravel學(xué)習(xí)筆記Route,Middleware和Controller參數(shù)傳遞

    摘要:本文主要學(xué)習(xí)總結(jié)下間參數(shù)傳遞。開發(fā)時經(jīng)常碰到類似場景有時需要在中讀取中設(shè)置的和,有時也需要在中讀取中設(shè)置的參數(shù)。總結(jié)下這幾個知識點,便于查閱。 本文主要學(xué)習(xí)總結(jié)下Route,Middleware,Controller間參數(shù)傳遞。開發(fā)時經(jīng)常碰到類似場景:有時需要在Middleware中讀取Route中設(shè)置的middleware parameter和route parameter,有時也需...

    zhangyucha0 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<