目次
詳細なソースコード解析" >詳細なソースコード解析
ホームページ PHPフレームワーク Laravel この記事を読めばLaravelの仕組みがしっかり理解できます!

この記事を読めばLaravelの仕組みがしっかり理解できます!

Dec 23, 2020 am 09:12 AM
laravel

以下は、Laravel Framework チュートリアルコラムからの Laravel の動作原理の紹介です。

まえがき

知っていても、知っていても、このフレームワークに初めて触れたとき、ほとんどの人は実装方法がわからず混乱するはずです。 「確実な方法はありません。フレームワークの基礎知識があり、フレームワークのソースコードに直接アクセスすると、すぐに挫折してしまいます。Laravel フレームワークは非常に優れた PHP です。」フレームワークについては、この記事でしっかり理解できます フレームワークの動作原理は、面接での話(自慢)の材料になります 優れたフレームワークのソースコードを学び、研究することは、自社の技術向上にもつながります 次に、シートベルトを締めてください。経験豊富なドライバーが運転を始めます。 ! !

準備知識

  • 一般的な配列メソッド、クロージャー関数の使用、マジック メソッドの使用など、PHP の基本的な知識を理解しておいてください。
  • PHP のリフレクション メカニズムと依存関係の注入に精通している
  • PHP 名前空間の概念と自動読み込みの構成に精通している
  • 一般的なデザイン パターン (シングルトン モード、ファクトリなどを含む) に精通しているモード、ファサード モード、登録ツリー モード、デコレータ モードなど。

動作原理の概要

Laravel のエントリ ファイルFrameworkindex.php

1. 自動読み込みの導入 autoload.php file

2. アプリケーション インスタンスの作成と同時に完了

基本绑定($this、容器类Container等等)、

基本服务提供者的注册(Event、log、routing)、

核心类别名的注册(比如db、auth、config、router等)
ログイン後にコピー

3. 開始Http リクエスト処理

make 方法从容器中解析指定的值为实际的类,比如 $app->make(Illuminate\Contracts\Http\Kernel::class); 解析出来 App\Http\Kernel 

handle 方法对 http 请求进行处理

实际上是 handle 中 sendRequestThroughRouter 处理 http 的请求

首先,将 request 绑定到共享实例

然后执行 bootstarp 方法,运行给定的引导类数组 $bootstrappers,这里是重点,包括了加载配置文件、环境变量、服务提供者、门面、异常处理、引导提供者等

之后,进入管道模式,经过中间件的处理过滤后,再进行用户请求的分发

在请求分发时,首先,查找与给定请求匹配的路由,然后执行 runRoute 方法,实际处理请求的时候 runRoute 中的 runRouteWithinStack 

最后,经过 runRouteWithinStack 中的 run 方法,将请求分配到实际的控制器中,执行闭包或者方法,并得到响应结果
ログイン後にコピー

4. 処理結果を返す

1. 自動ロード クラスを登録し、ファイルの自動ロードを実装します。

require __DIR__.'/../vendor/autoload.php';
ログイン後にコピー

2. アプリケーション コンテナ インスタンス Application を作成します (このインスタンスはコンテナ クラス Container を継承します) )、コア (Web、コマンド ライン、例外) をバインドして、必要なときに解析しやすくします。

$app = require_once __DIR__.'/../bootstrap/app.php';
ログイン後にコピー

app.php ファイルは次のとおりです:

<?php
// 创建Laravel实例 【3】
$app = new Illuminate\Foundation\Application(
 $_ENV[&#39;APP_BASE_PATH&#39;] ?? dirname(__DIR__)
);
// 绑定Web端kernel
$app->singleton(
 Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class);
// 绑定命令行kernel
$app->singleton(
 Illuminate\Contracts\Console\Kernel::class, App\Console\Kernel::class);
// 绑定异常处理
$app->singleton(
 Illuminate\Contracts\Debug\ExceptionHandler::class, App\Exceptions\Handler::class);
// 返回应用实例
return $app;
ログイン後にコピー

3. コンストラクターでアプリケーション インスタンス (Application.php) を作成するときに、基本バインディングをコンテナーに登録し、すべての基本サービス プロバイダーを登録し、コンテナーにコア カテゴリ名を登録します。

3.1. 基本バインディングをコンテナーに登録します Medium

    /**
     * Register the basic bindings into the container.
     *
     * @return void
     */
    protected function registerBaseBindings()
    {
        static::setInstance($this);
        $this->instance(&#39;app&#39;, $this);
        $this->instance(Container::class, $this);
        $this->singleton(Mix::class);
        $this->instance(PackageManifest::class, new PackageManifest(
            new Filesystem, $this->basePath(), $this->getCachedPackagesPath()
        ));
        # 注:instance方法为将...注册为共享实例,singleton方法为将...注册为共享绑定
    }
ログイン後にコピー

3.2. すべての基本サービス プロバイダー (イベント、ログ、ルーティング) を登録します

protected function registerBaseServiceProviders()
    {
        $this->register(new EventServiceProvider($this));
        $this->register(new LogServiceProvider($this));
        $this->register(new RoutingServiceProvider($this));
    }
ログイン後にコピー

3.3. コア カテゴリ名をコンテナ

#4. 上記により、クラスの自動ロード、サービスプロバイダーの登録、コアクラスのバインド、および基本登録のバインドが完了します

5. 開始

http

<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>index.php //5.1 $kernel = $app-&gt;make(Illuminate\Contracts\Http\Kernel::class); //5.2 $response = $kernel-&gt;handle( $request = Illuminate\Http\Request::capture());</pre><div class="contentsignin">ログイン後にコピー</div></div>5.1 のリクエストを解析します。make メソッドは、コンテナ

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

中的Illuminate\Contracts\Http\Kernel::class 是在index.php 中的$app = require_once __DIR__.&#39;/../bootstrap/app.php&#39;;这里面进行绑定的,实际指向的就是App\Http\Kernel::class这个类
ログイン後にコピー

5.2 から指定された値を解析します。ここで http リクエストが処理されます

$response = $kernel->handle(
 $request = Illuminate\Http\Request::capture());
ログイン後にコピー

Enter

$kernel

表現されたクラス App\Http\Kernel.php では、一部のミドルウェア関連コンテンツのみが定義されており、handle メソッドがないことがわかります。 その親に行きましょうクラス

use Illuminate\Foundation\Http\Kernel as HttpKernel

; でハンドル メソッドを見つけます。ハンドル メソッドがこのようなものであることがわかります<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">public function handle($request){ try { $request-&gt;enableHttpMethodParameterOverride(); // 最核心的处理http请求的地方【6】 $response = $this-&gt;sendRequestThroughRouter($request); } catch (Exception $e) { $this-&gt;reportException($e); $response = $this-&gt;renderException($request, $e); } catch (Throwable $e) { $this-&gt;reportException($e = new FatalThrowableError($e)); $response = $this-&gt;renderException($request, $e); } $this-&gt;app[&amp;#39;events&amp;#39;]-&gt;dispatch( new Events\RequestHandled($request, $response) ); return $response;}</pre><div class="contentsignin">ログイン後にコピー</div></div>6.

Http

リクエストを処理します (request を共有インスタンスにバインドし、パイプライン モードを使用してユーザー リクエストを処理します) <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php的handle方法// 最核心的处理http请求的地方$response = $this-&gt;sendRequestThroughRouter($request);protected function sendRequestThroughRouter($request){ // 将请求$request绑定到共享实例 $this-&gt;app-&gt;instance(&amp;#39;request&amp;#39;, $request); // 将请求request从已解析的门面实例中清除(因为已经绑定到共享实例中了,没必要再浪费资源了) Facade::clearResolvedInstance(&amp;#39;request&amp;#39;); // 引导应用程序进行HTTP请求 $this-&gt;bootstrap();【7、8】 // 进入管道模式,经过中间件,然后处理用户的请求【9、10】 return (new Pipeline($this-&gt;app)) -&gt;send($request) -&gt;through($this-&gt;app-&gt;shouldSkipMiddleware() ? [] : $this-&gt;middleware) -&gt;then($this-&gt;dispatchToRouter());}</pre><div class="contentsignin">ログイン後にコピー</div></div>7.

bootstrap 内

メソッド、指定されたブートストラップ クラス配列を実行します$bootstrappers、構成ファイル、環境変数、サービス プロバイダー、ファサード、例外処理、ブート プロバイダーを読み込みます。非常に重要な手順で、vendor/ にあります。 laravel/framework/src/Illuminate/Foundation/ Http/Kernel.php<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">/** * Bootstrap the application for HTTP requests. * * @return void */public function bootstrap(){ if (! $this-&gt;app-&gt;hasBeenBootstrapped()) { $this-&gt;app-&gt;bootstrapWith($this-&gt;bootstrappers()); }}</pre><div class="contentsignin">ログイン後にコピー</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">/** * 运行给定的引导类数组 * * @param string[] $bootstrappers * @return void */public function bootstrapWith(array $bootstrappers){ $this-&gt;hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) { $this[&amp;#39;events&amp;#39;]-&gt;dispatch(&amp;#39;bootstrapping: &amp;#39;.$bootstrapper, [$this]); $this-&gt;make($bootstrapper)-&gt;bootstrap($this); $this[&amp;#39;events&amp;#39;]-&gt;dispatch(&amp;#39;bootstrapped: &amp;#39;.$bootstrapper, [$this]); }}/** * Get the bootstrap classes for the application. * * @return array */protected function bootstrappers(){ return $this-&gt;bootstrappers;}/** * 应用程序的引导类 * * @var array */protected $bootstrappers = [ // 加载环境变量 \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, // 加载config配置文件【重点】 \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, // 加载异常处理 \Illuminate\Foundation\Bootstrap\HandleExceptions::class, // 加载门面注册 \Illuminate\Foundation\Bootstrap\RegisterFacades::class, // 加载在config/app.php中的providers数组里所定义的服务【8 重点】 \Illuminate\Foundation\Bootstrap\RegisterProviders::class, // 记载引导提供者 \Illuminate\Foundation\Bootstrap\BootProviders::class,];</pre><div class="contentsignin">ログイン後にコピー</div></div>8. # の

providers

配列で定義されたサービス <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">Illuminate\Auth\AuthServiceProvider::class,Illuminate\Broadcasting\BroadcastServiceProvider::class,....../** * 自己添加的服务提供者 */\App\Providers\HelperServiceProvider::class,</pre><div class="contentsignin">ログイン後にコピー</div></div> をロードします##config/app.php 一般的に使用される Redis、セッション、キュー、認証、データベース、Route

およびその他のサービスがここに読み込まれていることがわかります

9。パイプライン モードでユーザー リクエストを処理するには、最初にミドルウェア プロセスとフィルター

return (new Pipeline($this->app))
    ->send($request)
    // 如果没有为程序禁用中间件,则加载中间件(位置在app/Http/Kernel.php的$middleware属性)
    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
    ->then($this->dispatchToRouter());}
ログイン後にコピー

app/Http/Kernel.php

/**
 * 应用程序的全局HTTP中间件
 *
 * These middleware are run during every request to your application.
 *
 * @var array
 */protected $middleware = [
    \App\Http\Middleware\TrustProxies::class,
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,];
ログイン後にコピー

10 を通過します。ミドルウェア処理後、リクエストの配布 (一致するルートの検索を含む)

/**
 * 10.1 通过中间件/路由器发送给定的请求
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
 protected function sendRequestThroughRouter($request){
    ...
    return (new Pipeline($this->app))
        ...
        // 进行请求分发
        ->then($this->dispatchToRouter());}
ログイン後にコピー
/**
 * 10.2 获取路由调度程序回调
 *
 * @return \Closure
 */protected function dispatchToRouter(){
    return function ($request) {
        $this->app->instance(&#39;request&#39;, $request);
        // 将请求发送到应用程序
        return $this->router->dispatch($request);
    };}
ログイン後にコピー
/**
 * 10.3 将请求发送到应用程序
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
 */
 public function dispatch(Request $request){
    $this->currentRequest = $request;
    return $this->dispatchToRoute($request);}
ログイン後にコピー
 /**
 * 10.4 将请求分派到路由并返回响应【重点在runRoute方法】
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
 */public function dispatchToRoute(Request $request){   
    return $this->runRoute($request, $this->findRoute($request));}
ログイン後にコピー
/**
 * 10.5 查找与给定请求匹配的路由
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Routing\Route
 */protected function findRoute($request){
    $this->current = $route = $this->routes->match($request);
    $this->container->instance(Route::class, $route);
    return $route;}
ログイン後にコピー
/**
 * 10.6 查找与给定请求匹配的第一条路由
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Routing\Route
 *
 * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
 */public function match(Request $request){
    // 获取用户的请求类型(get、post、delete、put),然后根据请求类型选择对应的路由
    $routes = $this->get($request->getMethod());
    // 匹配路由
    $route = $this->matchAgainstRoutes($routes, $request);
    if (! is_null($route)) {
        return $route->bind($request);
    }
    $others = $this->checkForAlternateVerbs($request);
    if (count($others) > 0) {
        return $this->getRouteForMethods($request, $others);
    }
    throw new NotFoundHttpException;}
ログイン後にコピー

これまでに、リクエストに一致するルートが見つかり、後で実行されます。これは、10.4

/**
 * 10.7 返回给定路线的响应
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Routing\Route  $route
 * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
 */protected function runRoute(Request $request, Route $route){
    $request->setRouteResolver(function () use ($route) {
        return $route;
    });
    $this->events->dispatch(new Events\RouteMatched($route, $request));
    return $this->prepareResponse($request,
        $this->runRouteWithinStack($route, $request)
    );}
ログイン後にコピー
/**
 * Run the given route within a Stack "onion" instance.
 * 10.8 在栈中运行路由,先检查有没有控制器中间件,如果有先运行控制器中间件
 *
 * @param  \Illuminate\Routing\Route  $route
 * @param  \Illuminate\Http\Request  $request
 * @return mixed
 */protected function runRouteWithinStack(Route $route, Request $request){
    $shouldSkipMiddleware = $this->container->bound(&#39;middleware.disable&#39;) &&
                            $this->container->make(&#39;middleware.disable&#39;) === true;
    $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);
    return (new Pipeline($this->container))
        ->send($request)
        ->through($middleware)
        ->then(function ($request) use ($route) {
            return $this->prepareResponse(
                $request, $route->run()
            );
        });}
ログイン後にコピー
 /**
     * Run the route action and return the response.
     * 10.9 最后一步,运行控制器的方法,处理数据
     * @return mixed
     */
    public function run()
    {
        $this->container = $this->container ?: new Container;

        try {
            if ($this->isControllerAction()) {
                return $this->runController();
            }

            return $this->runCallable();
        } catch (HttpResponseException $e) {
            return $e->getResponse();
        }
    }
ログイン後にコピー
11 の runRoute メソッドです。ルートを実行して、応答を返します (強調)

ご覧のとおり、10.7 の 1 つのメソッドは

prepareResponse

です。これは、指定された値から応答インスタンスを作成し、
runRouteWithinStack メソッドはスタック内のルートを実行します。つまり、 http リクエストとレスポンスの両方がここで完了します。

概要

これまでのところ、Laravel フレームワークの実行プロセス全体が分析され、Laravel フレームワークの謎が明らかになりました。 Veil 氏が明らかにしました、記事を読みやすくするため、コアコードのみを記載しています。ソースコードは記事と合わせて自分で読む必要があります。記事に記載されている予備知識を理解する必要があることに注意してください。これはフレームワークのソース コードを読むための前提と基礎です。皆さんも何かを学んで車から降りていただければ幸いです。 ! !

以上がこの記事を読めばLaravelの仕組みがしっかり理解できます!の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHP でオブジェクト リレーショナル マッピング (ORM) を使用してデータベース操作を簡素化するにはどうすればよいですか? PHP でオブジェクト リレーショナル マッピング (ORM) を使用してデータベース操作を簡素化するにはどうすればよいですか? May 07, 2024 am 08:39 AM

PHP でのデータベース操作は、オブジェクトをリレーショナル データベースにマップする ORM を使用して簡素化されます。 Laravel の EloquentORM を使用すると、オブジェクト指向構文を使用してデータベースと対話できます。モデル クラスを定義したり、Eloquent メソッドを使用したり、実際にブログ システムを構築したりすることで ORM を使用できます。

Laravel と CodeIgniter の最新バージョンの比較 Laravel と CodeIgniter の最新バージョンの比較 Jun 05, 2024 pm 05:29 PM

Laravel 9 と CodeIgniter 4 の最新バージョンでは、更新された機能と改善が提供されます。 Laravel9はMVCアーキテクチャを採用しており、データベース移行、認証、テンプレートエンジンなどの機能を提供します。 CodeIgniter4 は、HMVC アーキテクチャを使用してルーティング、ORM、およびキャッシュを提供します。パフォーマンスの面では、Laravel9 のサービスプロバイダーベースの設計パターンと CodeIgniter4 の軽量フレームワークにより、優れたパフォーマンスが得られます。実際のアプリケーションでは、Laravel9 は柔軟性と強力な機能を必要とする複雑なプロジェクトに適しており、CodeIgniter4 は迅速な開発や小規模なアプリケーションに適しています。

Laravel - アーティザンコマンド Laravel - アーティザンコマンド Aug 27, 2024 am 10:51 AM

Laravel - アーティザン コマンド - Laravel 5.7 には、新しいコマンドを処理およびテストするための新しい方法が付属しています。これには職人コマンドをテストする新しい機能が含まれており、そのデモについては以下で説明します。

Laravel と CodeIgniter のデータ処理機能はどのように比較されますか? Laravel と CodeIgniter のデータ処理機能はどのように比較されますか? Jun 01, 2024 pm 01:34 PM

Laravel と CodeIgniter のデータ処理機能を比較します。 ORM: Laravel はクラスとオブジェクトのリレーショナル マッピングを提供する EloquentORM を使用しますが、CodeIgniter は ActiveRecord を使用してデータベース モデルを PHP クラスのサブクラスとして表します。クエリビルダー: Laravel には柔軟なチェーンクエリ API がありますが、CodeIgniter のクエリビルダーはよりシンプルで配列ベースです。データ検証: Laravel はカスタム検証ルールをサポートする Validator クラスを提供しますが、CodeIgniter には組み込みの検証関数が少なく、カスタム ルールの手動コーディングが必要です。実践例:ユーザー登録例はLarを示しています

Laravel と CodeIgniter ではどちらが初心者に優しいでしょうか? Laravel と CodeIgniter ではどちらが初心者に優しいでしょうか? Jun 05, 2024 pm 07:50 PM

初心者にとって、CodeIgniter は学習曲線が緩やかで機能は少ないですが、基本的なニーズはカバーしています。 Laravel は幅広い機能セットを提供しますが、学習曲線はわずかに急になります。パフォーマンスの点では、Laravel と CodeIgniter はどちらも良好なパフォーマンスを示します。 Laravel にはより広範なドキュメントとアクティブなコミュニティ サポートがあり、CodeIgniter はよりシンプルで軽量で、強力なセキュリティ機能を備えています。ブログアプリケーションを構築する実際のケースでは、Laravel の EloquentORM を使用するとデータ操作が簡素化されますが、CodeIgniter ではより手動の構成が必要になります。

Laravel と CodeIgniter: 大規模プロジェクトにはどちらのフレームワークが適していますか? Laravel と CodeIgniter: 大規模プロジェクトにはどちらのフレームワークが適していますか? Jun 04, 2024 am 09:09 AM

大規模プロジェクト用のフレームワークを選択する場合、Laravel と CodeIgniter にはそれぞれ独自の利点があります。 Laravel はエンタープライズレベルのアプリケーション向けに設計されており、モジュール設計、依存関係の注入、強力な機能セットを提供します。 CodeIgniter は、速度と使いやすさを重視した、小規模から中規模のプロジェクトに適した軽量フレームワークです。複雑な要件と多数のユーザーを伴う大規模なプロジェクトには、Laravel のパワーとスケーラビリティがより適しています。単純なプロジェクトやリソースが限られている状況では、CodeIgniter の軽量で迅速な開発機能がより理想的です。

PHPコードの単体テストと統合テスト PHPコードの単体テストと統合テスト May 07, 2024 am 08:00 AM

PHP 単体テストおよび統合テスト ガイド 単体テスト: コードまたは関数の単一単位に焦点を当て、PHPUnit を使用して検証用のテスト ケース クラスを作成します。統合テスト: 複数のコードユニットがどのように連携するかに注意し、PHPUnit の setUp() メソッドと TearDown() メソッドを使用してテスト環境をセットアップおよびクリーンアップします。実際のケース: PHPUnit を使用して、データベースの作成、サーバーの起動、テストコードの作成など、Laravel アプリケーションの単体テストと統合テストを実行します。

Laravel と CodeIgniter: 小規模プロジェクトにはどちらのフレームワークが適していますか? Laravel と CodeIgniter: 小規模プロジェクトにはどちらのフレームワークが適していますか? Jun 04, 2024 pm 05:29 PM

小規模なプロジェクトの場合、Laravel は強力な機能とセキュリティを必要とする大規模なプロジェクトに適しています。 CodeIgniter は、軽量さと使いやすさを必要とする非常に小規模なプロジェクトに適しています。

See all articles