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

資訊專欄INFORMATION COLUMN

PHP處理WEB請求的流程

zhangrxiang / 1091人閱讀

摘要:會依據協議,將請求的數據等信息發送給解析器,接下來解析器會解析文件,初始化執行環境,然后處理請求,再以規定的格式返回處理后的結果,退出進程。它的特點是會在動態分配處理進程給請求,以達到提高效率的目的,大多數實現都會維護一個進程池。

PHP作為世界上最好的編程語音,被廣泛的運用到Web開發中。因為其語法和C類似,有著非常平緩的學習曲線,越來越多的人使用PHP進行Web產品的快速開發。PHP世界里也涌現了很多開發框架,比如Laravel、ThinkPHP等,但不論何總框架,他們在處理Web請求時的模式都是一樣的,本文首先闡述PHP開發Web應用的基本架構,然后分別分析Laravel和ThinkPHP在處理Web請求時的處理流程。

PHP開發Web應用的基本架構

PHP開發Web應用時所以的請求需要指向具體的入口文件。WebServer是一個內容分發者,他接受用戶的請求后,如果是請求的是css、js等靜態文件,WebServer會找到這個文件,然后發送給瀏覽器;如果請求的是/index.php,根據配置文件,WebServer知道這個不是靜態文件,需要去找PHP解析器來處理,那么他會把這個請求簡單處理后交給PHP解析器。

WebServer會依據CGI協議,將請求的Url、數據、Http Header等信息發送給PHP解析器,接下來PHP解析器會解析php.ini文件,初始化執行環境,然后處理請求,再以CGI規定的格式返回處理后的結果,退出進程。web server再把結果返回給瀏覽器。整個處理過程如上圖所示。

FastCGI

這里的PHP解析器就是實現了CGI協議的程序,每次請求到來時他會解析php.ini文件,初始化執行環境,這就導致PHP解析器性能低下,于是就出現了CGI的改良升級版FastCGI。FastCGI是一種語言無關的協議,用來溝通程序(如PHP, Python, Java)和Web服務器(Apache2, Nginx), 理論上任何語言編寫的程序都可以通過FastCGI來提供Web服務。它的特點是會在動態分配處理進程給請求,以達到提高效率的目的,大多數FastCGI實現都會維護一個進程池。FastCGI會先啟一個master進程,解析配置文件,初始化執行環境,然后再啟動多個worker進程。當請求過來時,master進程會這個請求傳遞給一個worker進程,然后立即接受下一個請求。而且當worker進程不夠用時,master可以根據配置預先啟動幾個worker進程等待;當然空閑worker進程太多時,也會自動關閉,這樣就提高了性能,節約了系統資源。整個過程FastCGI扮演著對CGI進程進行管理的角色。

PHP-FPM

PHP-FPM是一個專門針對PHP實現了FastCGI協議的程序,它實際上就是一個PHP FastCGI進程管理器,負責管理一個進程池,調用PHP解析器來處理來自Web服務器的請求。PHP-FPM能夠對php.ini文件的修改進行平滑過度。

新建一個helloworld.php文件,寫入下列代碼

配置好WebServer和PHP-FPM等php運行環境后,在瀏覽器中訪問該文件就可以直接得到輸出。

基于PHP的Web框架
PHP Web框架是

基于某模式將PHP開發常用功能封裝實現使開發者快速開發的工具

它主要的任務包括:

代碼重用:定義包、類、函數的放置和加載規則,建議直接整合Composer及其AutoLoad特性。

請求的分發管理:這個就是路由,Rest風的框架喜歡Rewrite,簡單的一點的框架主要通過參數來定位模塊和方法所在。

配置文件管理:加載和動態加載配置數據

錯誤和異常管理:異常捕捉、錯誤日志記錄以及錯誤碼規范。

Layout和模板引擎:如何規劃頁面布局、widget如何重用、ajax頁面如何結合、過期- session如何重定向;數據和模板怎么渲染成HTML,是否壓縮和設置過期頭。

數據庫:如何融入控制器;支持什么樣的driver;考慮主從分離的擴展性;以及是否使用ORM

ThinkPHP3.2框架處理流程分析

TP的設計邏輯就是簡單粗暴,面對問題解決問題,所以他的處理流程是基于面向過程的思想,而沒有采用面向對象的依賴注入、控制反轉等思路。他的自動加載、錯誤處理通過php原生函數的回調來實現。TP處理每次請求要經過四個步驟如下圖所示:

調用應用路口index.php

index.php是TP的入口文件,所有的請求都由該文件接管,它的工作也很簡單主要是引入ThinkPHP入口文件

 5.3.0 !");


 


// 開啟調試模式 建議開發階段開啟 部署階段注釋或者設為false


define("APP_DEBUG",False);


 


// 定義應用目錄


define("APP_PATH","./Application/");


 


// 引入ThinkPHP入口文件


require
"./ThinkPHP/ThinkPHP.php";
載入框架入口文件ThinkPHP.php

在ThinkPHP.php中主要記錄初始運行時間和內存開銷,然后完成系統常量判斷及定義,最后載入框架引導類(ThinkThink)并執行Think::start方法進行應用初始化。

應用初始化ThinkThink:start()

應用初始化首先設置錯誤處理機制和自動加載機制

static public function start() {
      // 注冊AUTOLOAD方法
      spl_autoload_register("ThinkThink::autoload");      
      // 設定錯誤和異常處理
      register_shutdown_function("ThinkThink::fatalError");
      set_error_handler("ThinkThink::appError");
      set_exception_handler("ThinkThink::appException");

然后加載相關配置文件和運行模式定義文件,最后調用ThinkApp類的run方法啟動應用

運行應用App::run()

此后TP進入請求處理管道,TP為管道中定義了14個事件,每個事件都可以綁定回調函數,請求到達管道后依次觸發這些事件,事件觸發后就會調用綁定到事件的回調函數,整個管道的生命周期由app_init開始,由app_end結束。具體實現上,TP將這些事件命名為標簽(位),也可以稱之為鉤子,將回調函數命名為行為,當應用程序運行到標簽的時候,就會被攔截下來,統一執行相關的行為。

Laravel框架處理流程分析
統一入口

Laravel框架使用了統一入口,入口文件:/public/index.php

make("IlluminateContractsHttpKernel");
 
//運行Kernel類的handle方法,主要動作是運行middleware和啟動URL相關的Contrller
$response = $kernel->handle(
    $request = IlluminateHttpRequest::capture()
);
 
//控制器返回結果之后的操作,暫時還沒看,以后補上
$response->send();
 
$kernel->terminate($request, $response);
自動加載文件

laravel的自動加載,其實也就是Composer的自動加載
Composer根據聲明的依賴關系,從相關庫的源下載代碼文件,并根據依賴關系在 Composer 目錄下生成供類自動加載的 PHP 腳本,使用的時候,項目開始處引入 “/vendor/autoload.php” 文件,就可以直接實例化這些第三方類庫中的類了。

服務容器——Laravel真正的核心

服務容器,也叫IoC容器,其實包含了依賴注入(DI)和控制反轉(IoC)兩部分,是Laravel的真正核心。其他的各種功能模塊比如 Route(路由)、Eloquent ORM(數據庫 ORM 組件)、Request and Response(請求和響應)等等等等,實際上都是與核心無關的類模塊提供的,這些類從注冊到實例化,最終被使用,其實都是 Laravel 的服務容器負責的。

啟動Kernel代碼

Kernel實例調用handle方法,意味著Laravel的核心和公用代碼已經準備完畢,此項目正式開始運行

代碼清單/app/Http/Kernel.php


"AppHttpMiddlewareAuthenticate",


        "auth.basic"
=>
"IlluminateAuthMiddlewareAuthenticateWithBasicAuth",


        "guest"
=>
"AppHttpMiddlewareRedirectIfAuthenticated",


        "test"
=>
"AppHttpMiddleware	estMiddleWare",


    ];


}

可以看到,其實這個文件里面沒有handle方法,只有一些屬性定義,所以真正的handle方法,實在父類里面實現的

代碼清單…/Illuminate/Foundation/Http/Kernel.php

//這個很重要,是項目的一些啟動引導項,Kernel的重要步驟中,首先就是啟動這些文件的bootstrap方法
protected $bootstrappers = [
        //檢測環境變量文件是否正常
        "IlluminateFoundationBootstrapDetectEnvironment",
        //取得配置文件,即把/config/下的所有配置文件讀取到容器(app()->make("config")可以查看所有配置信息)
        "IlluminateFoundationBootstrapLoadConfiguration",
        //綁定一個名字為log的實例到容器,怎么訪問??(app()->make("log"))
        "IlluminateFoundationBootstrapConfigureLogging",
        //設置異常抓取信息,這個還沒仔細看,但大概就是這個意思
        "IlluminateFoundationBootstrapHandleExceptions",
        //把/config/app.php里面的aliases項利用PHP庫函數class_alias創建別名,從此,我們可以使用App::make("app")方式取得實例
        "IlluminateFoundationBootstrapRegisterFacades",
        //把/config/app.php里面的providers項,注冊到容器
        "IlluminateFoundationBootstrapRegisterProviders",
        //運行容器中注冊的所有的ServiceProvider中得boot方法
        "IlluminateFoundationBootstrapBootProviders",
    ];
 
  //真正的handle方法
  public function handle($request)
    {
        try
        {
            //主要是這行,調度了需要運行的方法
            return $this->sendRequestThroughRouter($request);
        }
        catch (Exception $e)
        {
            $this->reportException($e);
            return $this->renderException($request, $e);
        }
    }
 
    protected function sendRequestThroughRouter($request)
    {
        $this->app->instance("request", $request);
        Facade::clearResolvedInstance("request");
        //運行上述$bootstrappers里面包含的文件的bootstrap方法,運行的作用,上面已經注釋
        $this->bootstrap();
        //這是在對URL進行調度之前,也就是運行Route之前,進行的一些準備工作
        return (new Pipeline($this->app))    
                    ->send($request)        
                    //需要運行$this->middleware里包含的中間件
                    ->through($this->middleware)
                    //運行完上述中間件之后,調度dispatchToRouter方法,進行Route的操作
                    ->then($this->dispatchToRouter());
    }
 
    //前奏執行完畢之后,進行Route操作
    protected function dispatchToRouter()
    {
        return function($request)
        {
            $this->app->instance("request", $request);
            //跳轉到Router類的dispatch方法
            return $this->router->dispatch($request);
        };
    }

下面就需要根據URL和/app/Http/routes.php文件,進行Route操作

文件清單…/Illuminate/Routing/Router.php

public
function
dispatch(Request
$request)


{


$this->currentRequest
=
$request;


//在4.2版本里面,Route有一個篩選屬性;5.0之后的版本,被Middleware代替


$response
=
$this->callFilter("before",
$request);


if
(is_null($response))


{    


//繼續調度


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


}


$response
=
$this->prepareResponse($request,
$response);


//在4.2版本里面,Route有一個篩選屬性;5.0之后的版本,被Middleware代替


$this->callFilter("after",
$request,
$response);


return
$response;


}


 


public
function
dispatchToRoute(Request
$request)


{


$route
=
$this->findRoute($request);


$request->setRouteResolver(function()
use
($route)


{


return
$route;


});


$this->events->fire("router.matched",
[$route,
$request]);


$response
=
$this->callRouteBefore($route,
$request);


if
(is_null($response))


{


//
 只看這一行,還是調度文件


$response
=
$this->runRouteWithinStack(


$route,
$request


);


}


$response
=
$this->prepareResponse($request,
$response);


$this->callRouteAfter($route,
$request,
$response);


return
$response;


}


 


protected
function
runRouteWithinStack(Route
$route,
Request
$request)


{


//
 取得routes.php里面的Middleware節點


$middleware
=
$this->gatherRouteMiddlewares($route);


//這個有點眼熟


return
(new
Pipeline($this->container))


->send($request)


//執行上述的中間件


->through($middleware)


->then(function($request)
use
($route)


{    


//到Controller類了


return
$this->prepareResponse(


$request,


//run控制器


$route->run($request)


);


});


}


 


public
function
run(Request
$request)


{


$this->container
=
$this->container
?:
new
Container;


try


{


if
(
!
is_string($this->action["uses"]))


return
$this->runCallable($request);


if
($this->customDispatcherIsBound())


//實際上是運行了這行


return
$this->runWithCustomDispatcher($request);


 


//其實我是直接想運行這行


return
$this->runController($request);


}


catch
(HttpResponseException
$e)


{


return
$e->getResponse();


}


}


 


//繼續調度,最終調度到.../Illuminate/Routing/ControllerDispatcher.php文件的dispatch方法


protected
function
runWithCustomDispatcher(Request
$request)


{


list($class,
$method)
=
explode("@",
$this->action["uses"]);


 


$dispatcher
=
$this->container->make("illuminate.route.dispatcher");


return
$dispatcher->dispatch($this,
$request,
$class,
$method);
}

文件清單…/Illuminate/Routing/ControllerDispatcher.php

public
function
dispatch(Route
$route,
Request
$request,
$controller,
$method)


    {


        $instance
=
$this->makeController($controller);


        $this->assignAfter($instance,
$route,
$request,
$method);


        $response
=
$this->before($instance,
$route,
$request,
$method);


        if
(is_null($response))


        {


            //還要調度


            $response
=
$this->callWithinStack(


                $instance,
$route,
$request,
$method


            );


        }


        return
$response;


    }


 


    protected
function
callWithinStack($instance,
$route,
$request,
$method)


    {


        //又是Middleware......有沒有忘記,官方文檔里面Middleware可以加在控制器的構造函數中!!沒錯,這個Middleware就是在控制器里面申明的


        $middleware
=
$this->getMiddleware($instance,
$method);


        //又是這個,眼熟吧


        return
(new
Pipeline($this->container))


                    ->send($request)


                    //再次運行Middleware


                    ->through($middleware)


                    ->then(function($request)
use
($instance,
$route,
$method)


                    {    


                        運行控制器,返回結果


                        return
$this->call($instance,
$route,
$method);


                    });


    }

終于到達控制器

轉自:http://www.eurekao.com/PHP-pr...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/22586.html

相關文章

  • LNMP運維追蹤技巧總結

    摘要:的運維追蹤技巧總結曾幾何時我開始運維公司的網站,經過一段時間的摸爬滾打,也算是總結了不少在服務器下調試追蹤各種網站錯誤的方法。 LNMP的運維追蹤技巧總結 曾幾何時我開始運維公司的LNMP網站,經過一段時間的摸爬滾打,也算是總結了不少在LNMP服務器下調試追蹤各種網站錯誤的方法。好記性不如爛筆頭,還是總結一下吧! 在開始我會梳理一下我所理解的一個web請求從發起到響應的各個階段服務器和...

    XboxYan 評論0 收藏0
  • LNMP運維追蹤技巧總結

    摘要:的運維追蹤技巧總結曾幾何時我開始運維公司的網站,經過一段時間的摸爬滾打,也算是總結了不少在服務器下調試追蹤各種網站錯誤的方法。 LNMP的運維追蹤技巧總結 曾幾何時我開始運維公司的LNMP網站,經過一段時間的摸爬滾打,也算是總結了不少在LNMP服務器下調試追蹤各種網站錯誤的方法。好記性不如爛筆頭,還是總結一下吧! 在開始我會梳理一下我所理解的一個web請求從發起到響應的各個階段服務器和...

    Cristalven 評論0 收藏0
  • (PHP7內核剖析-1) CGI與FastCGI

    摘要:是與之間數據交換的一種協議。當收到這個請求后,會啟動對應的程序,這里就是的解析器。接下來解析器會解析文件,初始化執行環境,然后處理請求,再以規定規定的格式返回處理后的結果,退出進程,再把結果返回給瀏覽器。 CGI:是 Web Server 與 Web Application 之間數據交換的一種協議。FastCGI:同 CGI,是一種通信協議,但比 CGI 在效率上做了一些優化。PHP-...

    rubyshen 評論0 收藏0
  • (PHP7內核剖析-1) CGI與FastCGI

    摘要:是與之間數據交換的一種協議。當收到這個請求后,會啟動對應的程序,這里就是的解析器。接下來解析器會解析文件,初始化執行環境,然后處理請求,再以規定規定的格式返回處理后的結果,退出進程,再把結果返回給瀏覽器。 CGI:是 Web Server 與 Web Application 之間數據交換的一種協議。FastCGI:同 CGI,是一種通信協議,但比 CGI 在效率上做了一些優化。PHP-...

    Salamander 評論0 收藏0

發表評論

0條評論

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