Laravel5.5源碼詳解 -- Laravel-debugbar及使用elementUI-ajax的注意事項

來源:互聯網
上載者:User
Laravel5.5源碼詳解 – Laravel-debugbar 及使用elementUI - ajax的注意事項

關於laravel對中介軟體的處理,請參中介軟體考另文,
Laravel5.5源碼詳解 – 中介軟體MiddleWare分析
這裡只是快速把debugbar的交易處理流程記錄一遍。

我在Illuminate\Pipeline\Pipeline的then函數中進行中介軟體捕獲,發現有下面這些中介軟體,

array:6 [▼  0 => "Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode"  1 => "Illuminate\Foundation\Http\Middleware\ValidatePostSize"  2 => "App\Http\Middleware\TrimStrings"  3 => "Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull"  4 => "App\Http\Middleware\TrustProxies"  5 => "Barryvdh\Debugbar\Middleware\InjectDebugbar"]array:6 [▼  0 => "App\Http\Middleware\EncryptCookies"  1 => "Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse"  2 => "Illuminate\Session\Middleware\StartSession"  3 => "Illuminate\View\Middleware\ShareErrorsFromSession"  4 => "App\Http\Middleware\VerifyCsrfToken"  5 => "Illuminate\Routing\Middleware\SubstituteBindings"]

其中就包括這個Barryvdh\Debugbar\Middleware\InjectDebugbar,它是在larave啟動時,在vendor\composer\installed.json發現並引入,

laravel-debugbar的配置在Barryvdh\laravel-debugbar\config\debugbar,裡面解釋比較詳盡,這裡也不再重複。順便說一下,這個類是在Barryvdh\Debugbar\ServiceProvider中註冊的,

<?php namespace Barryvdh\Debugbar;use Barryvdh\Debugbar\Middleware\DebugbarEnabled;use Barryvdh\Debugbar\Middleware\InjectDebugbar;use DebugBar\DataFormatter\DataFormatter;use DebugBar\DataFormatter\DataFormatterInterface;use Illuminate\Contracts\Http\Kernel;use Illuminate\Routing\Router;use Illuminate\Session\SessionManager;class ServiceProvider extends \Illuminate\Support\ServiceProvider{    protected $defer = false;    public function register()    {        $configPath = __DIR__ . '/../config/debugbar.php';        $this->mergeConfigFrom($configPath, 'debugbar');        $this->app->alias(            DataFormatter::class,            DataFormatterInterface::class        );        $this->app->singleton(LaravelDebugbar::class, function () {                $debugbar = new LaravelDebugbar($this->app);                if ($this->app->bound(SessionManager::class)) {                    $sessionManager = $this->app->make(SessionManager::class);                    $httpDriver = new SymfonyHttpDriver($sessionManager);                    $debugbar->setHttpDriver($httpDriver);                }                return $debugbar;            }        );        $this->app->alias(LaravelDebugbar::class, 'debugbar');        $this->app->singleton('command.debugbar.clear',            function ($app) {                return new Console\ClearCommand($app['debugbar']);            }        );        $this->commands(['command.debugbar.clear']);    }    // 這裡註冊了很多事件處理功能,都是後面在處理request的時候可能會用到的    public function boot()    {        $configPath = __DIR__ . '/../config/debugbar.php';        $this->publishes([$configPath => $this->getConfigPath()], 'config');        $routeConfig = [            'namespace' => 'Barryvdh\Debugbar\Controllers',            'prefix' => $this->app['config']->get('debugbar.route_prefix'),            'domain' => $this->app['config']->get('debugbar.route_domain'),            'middleware' => [DebugbarEnabled::class],        ];        $this->getRouter()->group($routeConfig, function($router) {            $router->get('open', [                'uses' => 'OpenHandlerController@handle',                'as' => 'debugbar.openhandler',            ]);            $router->get('clockwork/{id}', [                'uses' => 'OpenHandlerController@clockwork',                'as' => 'debugbar.clockwork',            ]);            $router->get('assets/stylesheets', [                'uses' => 'AssetController@css',                'as' => 'debugbar.assets.css',            ]);            $router->get('assets/javascript', [                'uses' => 'AssetController@js',                'as' => 'debugbar.assets.js',            ]);        });        $this->registerMiddleware(InjectDebugbar::class);    }    protected function getRouter()    {        return $this->app['router'];    }    protected function getConfigPath()    {        return config_path('debugbar.php');    }    protected function publishConfig($configPath)    {        $this->publishes([$configPath => config_path('debugbar.php')], 'config');    }    protected function registerMiddleware($middleware)    {        $kernel = $this->app[Kernel::class];        $kernel->pushMiddleware($middleware);    }    public function provides()    {        return ['debugbar', 'command.debugbar.clear', DataFormatterInterface::class, LaravelDebugbar::class];    }}

重點在這裡,實際處理response和request的handle函數在Barryvdh\Debugbar\Middleware\InjectDebugbar中,

<?php namespace Barryvdh\Debugbar\Middleware;use Error;use Closure;use Exception;use Illuminate\Http\Request;use Barryvdh\Debugbar\LaravelDebugbar;use Illuminate\Contracts\Container\Container;use Illuminate\Contracts\Debug\ExceptionHandler;use Symfony\Component\Debug\Exception\FatalThrowableError;class InjectDebugbar{    protected $container;      protected $debugbar;    protected $except = [];    public function __construct(Container $container, LaravelDebugbar $debugbar)    {        $this->container = $container;        $this->debugbar = $debugbar;        $this->except = config('debugbar.except') ?: [];    }    public function handle($request, Closure $next)    {        // 如果debugbar沒有使能,或傳入的request是空的,則直接返回。        if (!$this->debugbar->isEnabled() || $this->inExceptArray($request)) {            return $next($request);        }        // 註冊交易處理功能        $this->debugbar->boot();        try {            /** @var \Illuminate\Http\Response $response */            // 可以看到,handle是處理後置的,也就是在(來回兩次經過handle)回途中處理函數,            // 所以這裡先$next()            $response = $next($request);        } catch (Exception $e) {            $response = $this->handleException($request, $e);        } catch (Error $error) {            $e = new FatalThrowableError($error);            $response = $this->handleException($request, $e);        }        // 處理後置,接上面的next()之後才是debugbar幹活的時間        // Modify the response to add the Debugbar        $this->debugbar->modifyResponse($request, $response);        // 處理完畢,返回結果        return $response;    }

上面這段,真正起作用的就是這句:$this->debugbar->modifyResponse($request, $response); ,它是debugbar 修改response的地方所在,具體請看在Barryvdh\Debugbar\LaravelDebugbar,請注意其中的注釋,

public function modifyResponse(Request $request, Response $response){        // 如果沒有使能,就直接返回response        $app = $this->app;        if (!$this->isEnabled() || $this->isDebugbarRequest()) {            return $response;        }        // Show the Http Response Exception in the Debugbar, when available        // 如果有Http異常,則列印顯示出來        if (isset($response->exception)) {            $this->addThrowable($response->exception);        }        // 要不要調試設定資訊,預設是不需要的        if ($this->shouldCollect('config', false)) {            try {                $configCollector = new ConfigCollector();                $configCollector->setData($app['config']->all());                $this->addCollector($configCollector);            } catch (\Exception $e) {                $this->addThrowable(                    new Exception(                        'Cannot add ConfigCollector to Laravel Debugbar: ' . $e->getMessage(),                        $e->getCode(),                        $e                    )                );            }        }        // 如果綁定session調試        if ($this->app->bound(SessionManager::class)){            /** @var \Illuminate\Session\SessionManager $sessionManager */            $sessionManager = $app->make(SessionManager::class);            $httpDriver = new SymfonyHttpDriver($sessionManager, $response);            $this->setHttpDriver($httpDriver);            if ($this->shouldCollect('session') && ! $this->hasCollector('session')) {                try {                    $this->addCollector(new SessionCollector($sessionManager));                } catch (\Exception $e) {                    $this->addThrowable(                        new Exception(                            'Cannot add SessionCollector to Laravel Debugbar: ' . $e->getMessage(),                            $e->getCode(),                            $e                        )                    );                }            }        } else {            $sessionManager = null;        }        // 貌似這句的意思是,如果只調試一個session? 還沒進入源碼深究。        if ($this->shouldCollect('symfony_request', true) && !$this->hasCollector('request')) {            try {                $this->addCollector(new RequestCollector($request, $response, $sessionManager));            } catch (\Exception $e) {                $this->addThrowable(                    new Exception(                        'Cannot add SymfonyRequestCollector to Laravel Debugbar: ' . $e->getMessage(),                        $e->getCode(),                        $e                    )                );            }        }        // 如果要支援Clockwork調試,(比如支援Chrome外掛程式Clockwork調試)        if ($app['config']->get('debugbar.clockwork') && ! $this->hasCollector('clockwork')) {            try {                $this->addCollector(new ClockworkCollector($request, $response, $sessionManager));            } catch (\Exception $e) {                $this->addThrowable(                    new Exception(                        'Cannot add ClockworkCollector to Laravel Debugbar: ' . $e->getMessage(),                        $e->getCode(),                        $e                    )                );            }            $this->addClockworkHeaders($response);        }        // 首先判斷一下,這是不是一個redirect()的請求(重新整理頁面)        // 這個判斷的語句原型是$this->statusCode >= 300 && $this->statusCode < 400;        // 函數原型在vendor\symfony\http-foundation\Response.php中,        if ($response->isRedirection()) {            try {                $this->stackData();            } catch (\Exception $e) {                $app['log']->error('Debugbar exception: ' . $e->getMessage());            }        } elseif (        // 如果是ajax請求,並且已經設定了對ajax進行調試,則這在裡處理            $this->isJsonRequest($request) &&            $app['config']->get('debugbar.capture_ajax', true)        ) {            try {                $this->sendDataInHeaders(true);                if ($app['config']->get('debugbar.add_ajax_timing', false)) {                    $this->addServerTimingHeaders($response);                }            } catch (\Exception $e) {                $app['log']->error('Debugbar exception: ' . $e->getMessage());            }        } elseif (        // 如果headers有Content-Type這個標籤,並且不是html,那麼就應該是JSON資料        // 很明顯,這裡只對Content-Type=JSON的資料進行操作,        // 對其他類型的資料,如圖片,MSWORD等,則直接拋出異常            ($response->headers->has('Content-Type') &&                strpos($response->headers->get('Content-Type'), 'html') === false)            || $request->getRequestFormat() !== 'html'            || $response->getContent() === false        ) {            try {                // Just collect + store data, don't inject it.                $this->collect();            } catch (\Exception $e) {                $app['log']->error('Debugbar exception: ' . $e->getMessage());            }        } elseif ($app['config']->get('debugbar.inject', true)) {        // 對普通的情況,debugbar會在這裡修改的response,並注入渲染            try {                $this->injectDebugbar($response);            } catch (\Exception $e) {                $app['log']->error('Debugbar exception: ' . $e->getMessage());            }        }        return $response;    }

用到的 $app['config'] 的原貌是這樣的,

Repository {#24 ▼  #items: array:13 [▼    "app" =>
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.