ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える

咔咔
リリース: 2020-12-04 13:32:23
オリジナル
135 人が閲覧しました
"

この記事では、コントローラーのインスタンス化を紹介し、ArrayAccess とインスタンスを返すマジック アクセスの直接実行の違いを分析します

"

前書き

上記の記事では、ルーティングについて説明しています。特別に詳細な説明もアプリケーションの初期化と解析から始まり、ルート スケジューリングがルート検出に戻るまでです。

ルート検出で得られる値は以下の通りで、最終的にルートスケジューリングで返される値となります。

使用するルーティングルールは Route::get('hello/:name', 'index/index/:name');

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
印刷場所
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ルーティング検出の結果

上の図からわかるように、重要なデータはdispatchcに保存され、その後制御が行われます装置について詳しく説明されています。

最初に説明するのは、ルート検出が完了した後に実行されるインスタンス化コントローラーの操作です。

1. インスタンス化コントローラー

まずはインスタンス化コントローラーの実行方法を見てみましょう!

最初にエントリ ファイルからコードを実行する必要があることは間違いありません。ここでは、コンテナを使用して App のインスタンスを返し、次に App クラスの run メソッドを呼び出します。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
Entry file

は、上記で解析されたルートも使用されます。

つまり、検出ルートが実行された後、ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるが実行されます。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
アプリケーションを実行します

ルーティング検出が完了すると、リターンはthinkroutedispatchModule Object这个类,并且这个类赋值给了变量$dispatch

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ルーティング検出

次に、このメソッドのこのコードを見てください。ここではミドルウェアが使用されています。ここで簡単に説明します。コード クロージャは依然として使用されています。クロージャの概念がよくわからない場合は、基本に戻る必要があります。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ミドルウェア

上の図の丸で囲った場所が$dispatch->run() このコードは次に解析されます。 $dispatch->run()这块代码,接下来就要对这块代码进行解析了。

在检测路由最终的返回值可以知道其实这个方法是在thinkroutedispatchModule这个类中。

接着就需要对这个类中的run方法进行解析了,这个方法也就是ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える。

在这个方法中不管是获取路由参数还是检测路由、数据自动验证都不会执行(是按照咔咔上文给的路由地址为案例)。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える

所以根据上图代码就会执行到$data = $this->exec();

ルートの最終的な戻り値を検出した後、このメソッドが実際には thinkroutedispatchModule をこのクラスに追加します。

次に、このクラスの run メソッドを分析する必要があります。これは、ルーティングのスケジューリングを実行するためのものです。
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるこの方法では、ルーティングパラメータの取得、ルーティングの検出、自動データ検証は実行されません(上記のルーティングアドレスは例として使用されます)。
ルーティング スケジューリングを実行
ルーティング スケジューリングを実行します

したがって、上記のコードに従って、コードは $data = $this->exec();ここにあります。

🎜このメソッドをトレースすると、次の図のArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるの存在がわかります。ここで知っておく必要があるのは、ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるです。 🎜🎜🎜🎜ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える🎜🎜🎜🎜ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるの説明🎜🎜
  • ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるはインスタンス化できません
  • 抽象メソッドを持つクラスはArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるである必要があります。クラスは抽象的に変更されている必要があります
  • 抽象メソッドには関数本体、つまり抽象関数 fun() を含めることはできません。
  • ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるの非抽象メソッドはサブクラスから呼び出すことができます
  • 非抽象サブクラスはArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるを継承し、サブクラスは親クラスのすべての抽象メソッドを実装する必要があります
  • 抽象サブクラスは継承せずにArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるを継承します親クラスの抽象メソッド

は、上の図の原理に従って見ることができますDispatchこのクラスはArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるです。 Dispatch这个类是ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える。

所以就会有俩种情况, 一种是ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える继承ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える,无需继承父类的抽象方法。

另一种是非抽象子类继承ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える,子类必须实现父类的所有抽象方法。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える

怎么去找谁继承了Dispatch

这个时候是不是有一个疑问就是怎么去找Dispatch的子类。

在这个图中可以看到本类Dispatch,但是还有一个dispatch这个目录。

根据ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える返回的数据可以轻而易举的就知道是thinkphp/library/think/route/dispatch/Module.php

つまり、2 つの状況が考えられます。1 つは、ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるが親クラスの抽象メソッドを継承せずに、ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるを継承する場合です。 🎜🎜もう 1 つは、非抽象サブクラスがArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるを継承し、サブクラスが親クラスのすべての抽象メソッドを実装する必要があることです。 🎜
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
🎜それを見つける方法Dispatch を継承するのは誰ですか🎜🎜このとき、Dispatch のサブクラスを見つける方法について質問があります。 🎜🎜この写真ではこのタイプのディスパッチが見られますが、ディスパッチディレクトリもあります。 🎜🎜ルート検出によって返されたデータによれば、thinkphp/library/think/route/dispatch/Module.phpこのクラス。 🎜
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
サブカテゴリを探しています

thinkphp/ library/think/route/dispatch/Module.phpViewexec メソッド。 thinkphp/library/think/route/dispatch/Module.php查看exec方法。

那么接下来的任务就是对这个方法进行深入的解读了。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える

先看第一行代码$this->app['hook']->listen('module_init');,在这里使用了容器ArrayAccess用数组的形式访问对象,然后执行的ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える__get,当访问不存在的属性时会去执行make方法。

使用编辑器追踪这个app会到thinkphp/library/think/route/Dispatch.php

それでは、次の課題は、この方法を詳しく説明することです。
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
コントローラーをインスタンス化します
まずコードの最初の行を確認してください$this->app['hook']->listen('module_init');、ここでコンテナ ArrayAccess は配列にアクセスします。オブジェクトをフォームに追加し、マジックメソッド __get を実行します。存在しない属性にアクセスすると、make メソッドが実行されます。

エディターを使用してこのアプリを追跡すると、thinkphp/library /think/route/Dispatch.phpこのクラスのコンストラクターで、App インスタンスが app 属性に割り当てられていることがわかります。 🎜🎜🎜🎜アプリクラスのインスタンス化を探します🎜🎜🎜そして、Appクラスに到達すると、それがContainerクラスを継承していることがわかります。 🎜
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
継承クラス

この知識ポイントについては、コンテナのコンテキストで何度も説明しましたが、存在しないプロパティにアクセスするには、戻ってコンテナの __get マジック メソッドを実行します。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
存在しないプロパティにアクセスするときにマジックメソッドが実行されます

そのため、このブロックのパラメータがフックに渡され、フックのインスタンスが返されることになります。このインスタンスがどのように返されるかについては、で説明されています。コンテナに関するセクションが詳しく説明されていますので、ぜひご覧ください。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
フックのインスタンスを返します

その後、フックの listen メソッドが実行されて、タグの動作を監視します。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
タグの動作を聞いてください

この時点で、このパラメータがモジュールに対して初期化されていることがわかりますが、この値は空です。

つまり、上の図では実行されないので、簡単なテストのためにこのパラメータにアプリケーションの初期化値を入れます。

このクラスはファサードクラスを最適化する実行フックです。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
動作拡張定義ファイルを適用します

その後、コードが実行され、$results[$key] = $this->execTag($name, $tag, $params);ここです。 $results[$key] = $this->execTag($name, $tag, $params);这里来。

参数说明

  • $name = string(22) "behaviorLoadBehavior"
  • $tag = module_init

接着通过正则对传过来的参数进行处理,最终返回moduleInit

然后通过$obj = Container::get($class);返回behaviorLoadBehavior的实例

最终通过is_callable这个函数进行验证,检测类里边的方法是否可以被调用,方法数组格式,这个方法后期咔咔单独写一篇文章作为对象来解析,这里只需要知道会返回false即可。

然后会把本类的$portal这个值赋值给$method,这个值就是run。

最后通过$result = $this->app->invoke($call, [$params]);

パラメータの説明

    $name = string(22) "behaviorLoadBehavior" /セクション>
  • $tag = module_init
その後、渡されたパラメータは正規表現を通じて処理され、最後に moduleInit が返されます

次に $obj = Container::get($class);behaviorLoadBehavior のインスタンスを返します

最後に渡されましたis_callableこの関数は、クラス内のメソッドを呼び出すことができるかどうかを検証します。このメソッドの後に、Kaka は解析するオブジェクトとして別の記事を作成します。ここでは false が返されることだけを知っておく必要があります。 🎜🎜次に、$portalこの値は$method、この値は走る。 🎜🎜最後に$result = $this->app ->invoke($call, [$params]);このコード行、このコード行の一番下の実行は、リフレクション メカニズムを通じて実装されます。 🎜🎜最後のコードは NULL を返します。 🎜🎜🎜ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える🎜🎜

次のステップは、コントローラーをインスタンス化することです。呼び出しメソッドは $this->app->controller()$this->app->controller()

这里需要注意的是list这个函数,这个函数的后边会返回一个数组,然后list中的俩个变量会分别为索引0和1。

判断也会去执行第一个,同样会执行到容器类的make方法,这个方法会直接返回appindexcontrollerIndex

ここで注意する必要があるのは list 関数です。この関数の後に配列が返され、リスト内の 2 つの変数が返されます。インデックス 0 と 1。
实例化(分层)控制器 格式:[模块名/]控制器名最初の判定も実行され、コンテナ クラスの make メソッドも実行され、このメソッドは appindexcontrollerIndexこのクラスのインスタンス。

インスタンス化(階層化)コントローラーの形式: [モジュール名/]コントローラー名2. ArrayAccessとインスタンスを返すマジックアクセスの直接実行の違いについて

すでに学習している友達もいますArrayAccess とマジック メソッド __get の使用。

この 2 つの場所で曖昧な部分があると推測されます。Kaka はこれら 2 つをまとめて分析します。

まず ArrayAccess の使用方法について話しましょう

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるこのケースは、主に ArrayAccess クラスを実装するために以前にデモしました。

これは以前に書いたテストメソッドです

そして、それを使用するためにコントローラーに来たら、最初にインスタンス化します。以前に実装されたケースは次のとおりです。 🎜🎜しかし、今回実装する必要があるケースは、下の図に実装されているものではありません。 🎜
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
コントローラーを使用する

次に、下図に示すメソッドを使用して、配列を使用してオブジェクトのプロパティに直接アクセスします。

上の図では、属性 title が kaka に設定されていることがわかります。この場合、配列の形式で直接取得されます。

戻り結果が kaka であることを確認してください。これは、オブジェクトのプロパティが配列形式で直接アクセスされていることを意味します。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
新しいアクセスアクセス
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
結果の印刷

概要

最初のケースの実装プロセスでは、オブジェクトを使用してオブジェクトのプロパティに直接アクセスするステップが無視されました。配列の形式で。

目に見えるものは直接取得できるので、この考え方をフレームワークに落とし込んで見てみましょう。

フレームワーク実践事例

前回の記事で解析したルートには以下のコードが存在します。簡単に解析してみましょう。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ルーティング クラス

まず、印刷時のこのアプリの値を見てみましょう: thinkApp オブジェクトオブジェクト。 thinkApp Object对象。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える

thinkApp Object这个对象去访问request时,因为app属性就没有这个request

印刷されたアプリの値
印刷されたアプリの値ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
when thinkApp オブジェクトアクセスするこのオブジェクトリクエスト、アプリ属性にこの がないためです。 ="フォントサイズ: 14px; ワードラップ: ブレークワード; パディング: 2px 4px; ボーダー半径: 4px; マージン: 0 2px; 背景色: rgba(27,31,35,.05); font- family: Operator Mono、Consolas、Monaco、Menlo、monospace; word-break: Break-all; color: rgb(271, 93, 108);">request、アプリ クラスはコンテナ クラスを継承するため、したがって、コンテナクラスに移動して、以下に示すメソッドを実行します。

このメソッドを実行しますArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える返回实例对象
すると、__getメソッドが実行され、makeメソッドが実行されて対応するインスタンスが返されます。

🎜このメソッドを実行してインスタンス オブジェクトを返します🎜🎜🎜この時点でまだ疑問がある場合は、実行すると言っているのになぜ実行されるだけなのでしょうか。 🎜

次に、Kaka が簡単なテストを行ってそれを確認します。

この位置にランダムな値を出力します。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
テストケース

次に、コンテナクラスのArrayAccessのoffsetGetメソッドに移動し、渡された値を出力します。

印刷された結果を見ると、非常に明確になります。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ここに画像の説明を挿入
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
結果を印刷

これも前回を踏まえた詳しい説明です 次にコンテナ内の内容については __get メソッドで説明します。詳細を参照して、__get メソッドがどのような状況で実行されるかを確認します。

__getメソッドの詳しい説明

この場合については、下の画像を参照してください$this->hook

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
アプリケーションを初期化します

同じ理由で、最初にこれをデバッグしましょう$this の値は何ですか。 $this是什么值。

打印这个值都没什么必要,因为就是在本类中。

ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える

在类中属性的访问应该都会,就是直接使用$this-> 即可。

所以说当系统访问$this->hook

この値はこのクラスにあるため、出力する必要はありません。
ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える結果の印刷
結果の印刷

クラスの属性$this-> で十分です。

したがって、システムが $this->フックこのとき、Appクラスにはhook属性がないため、コンテナクラスのマジックメソッドが実行されます。 ArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考える
Magicメソッド

次に、makeメソッドを実行してクラスのインスタンスを作成します。

🎜🎜🎜 クラスのインスタンスを作成する 🎜🎜🎜🎜 概要 🎜🎜

そこで、ArrayAccess と __get マジック メソッドを使用し、最終的に実行された make メソッドはクラスのインスタンスを返します。

this->config に遭遇すると、実行されるのはコンテナの __get メソッドです。

app['request']に遭遇すると、ArrayAccessが実行され、次にoffsetGetが実行されます

  • __getはクラスの属性に対して実行されます
  • ArrayAccess がインスタンス化される クラスが配列形式でアクセスされる場合、このメソッドが存在しない場合はこのメソッドが実行されます。 offsetGet

以上がArrayAccess とダイレクト マジック アクセス リターン インスタンスの違いについて ThinkPHP で考えるの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
1
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!