ホームページ >バックエンド開発 >PHPチュートリアル >PHP_PHP チュートリアルの基礎となるメカニズムを深く理解する

PHP_PHP チュートリアルの基礎となるメカニズムを深く理解する

WBOY
WBOYオリジナル
2016-07-13 17:46:161022ブラウズ

動的言語としての PHP はどのように実装され、その基礎となるメカニズムは何であり、どのような特性を持っているのでしょうか? この記事では、PHP の設計概念、全体的な構造、コア データ構造、変数などの関連する基礎知識をシンプルかつ簡単に紹介します。 -PHP プログラムの適切な開発、パフォーマンスの最適化などには、一定の指針となる重要性があります。

目次

1. 概要…

php とは?.

基本的な実装の目的を理解していますか?

2. phpの設計コンセプトと特徴

3. Php の 4 層システム...

4、サピ

5. PHP の実行プロセスとオペコード。

6. ハッシュテーブル — コアデータ構造…

7. PHP 変数…

概要…

ズヴァル

整数、浮動小数点型変数…

文字列変数…

配列変数…

リソースタイプ変数…

PHP変数のスコープ…

1. 概要

phpとは何ですか?

Web 開発用の動的言語。より具体的に言うと、C 言語を使用して多数のコンポーネントを実装するソフトウェア フレームワークです。より狭義には、強力な UI フレームワークと考えることができます。

基礎となる実装の目的を理解していますか?

  • 動的言語をうまく使用するには、まずそれを理解する必要があります
  • メモリ管理とフレームワーク モデルは学ぶ価値があります
  • 拡張開発を通じてより強力な機能を実現し、プログラムのパフォーマンスを最適化します

2. php

の設計思想と特徴
  • マルチプロセスモデル

PHP はマルチプロセス モデルであるため、異なるリクエストが互いに干渉することはなく、1 つのリクエストの失敗がサービス全体に影響を与えることはありません。もちろん、時代の発展により、PHP はすでにマルチプロセスをサポートしています。スレッドモデル。

  • 弱い型付き言語

C/C++、Java、C# などの言語とは異なり、Php は型指定が弱い言語です。変数の型は最初には決定されず、操作中に暗黙的または明示的な型変換が行われる可能性があります。は Web 開発において非常に便利で効率的です。これについては、後で PHP 変数で詳しく説明します。

  • エンジン(Zend)+コンポーネント(ext)モデルにより内部結合を軽減

  • 中間層 (sapi) は Web サーバーと php
  • を分離します

  • 構文はシンプルで柔軟であり、あまり多くの仕様はありません。 (結果としてスタイルが混在します)

  • どんなに下手なプログラマであっても、全体の状況を危険にさらすようなとんでもないプログラムは書きません。

3. Phpの4層システム

Phpのコアアーキテクチャは以下の通りです

写真からもわかるように、PHPは下から上まで4層構造になっています

  • ゼンドエンジン

Zend は完全に純粋な C で実装されており、PHP コード (字句解析や構文解析などの一連のコンパイル プロセス) を実行可能なオペコード処理に変換し、対応する処理メソッドを実装し、基本的なデータ構造 (ハッシュテーブルなど) を実装します。 、oo)、メモリの割り当てと管理、および外部呼び出しに対応する API メソッドを提供します。これはすべての周辺機能が zend を中心に実装されています。

  • 拡張機能

zend エンジンを中心に、拡張機能はコンポーネントベースの方法でさまざまな基本サービスを提供します。一般的なさまざまな組み込み関数 (配列シリーズなど) や標準ライブラリなどはすべて拡張機能を通じて実装されます。機能の拡張、パフォーマンスの最適化などを実現するために必要です (たとえば、現在 Tieba で使用されている PHP 中間層やリッチ テキスト解析が拡張の代表的なアプリケーションです)。

  • サピ

Sapi の正式名はサーバー アプリケーション プログラミング インターフェイスであり、Sapi は PHP 自体の非常にエレガントで成功した設計です。上位層のアプリケーションは分離され、分離されます。PHP は異なるアプリケーションとの互換性を考慮できなくなり、アプリケーション自体も独自の特性に応じて異なる処理方法を実装できます。後ほどサピ編で紹介します

  • 上位層アプリケーション

これは、私たちが通常作成する PHP プログラムです。Web サーバーを介して Web アプリケーションを実装したり、コマンド ラインでスクリプト モードで実行したりするなど、さまざまな Sapi メソッドを通じてさまざまなアプリケーション モードを取得できます。

php が車だったら、

  • 車のフレームワークはphpそのもの
  • Zend は車のエンジンです
  • Ext の下にあるさまざまなコンポーネントは車の車輪です
  • サピは道路に見立てられ、車はさまざまな種類の道路を走行できます

PHP プログラムの実行は、道路を走る車のようなものです。

したがって、次のものが必要です: 優れたエンジン + 適切なホイール + 適切なトラック

4.サピ

前に述べたように、sapi を使用すると、外部アプリケーションは一連のインターフェイスを通じて php とデータを交換し、さまざまなアプリケーションの特性に応じて特定の処理メソッドを実装できます。

    apache2ハンドラー
これは Web サーバーとして Apache を使用し、mod_php モードで実行する場合の処理​​方法であり、現在最も広く使用されています。

    CG
これは、有名な fastcgi プロトコルである Web サーバーと php の間のもう 1 つの直接対話方法であり、近年、fastcgi+php が使用されることが多くなり、非同期 Web サーバーでサポートされる唯一の方法でもあります。 fastcgi と mod_php については、別の記事「php パフォーマンス調査 - mod_php vs fastcgi」を参照してください

    クリ
コマンドラインから呼び出されるアプリケーションモード

Sapiの定義と主なインターフェース機能は以下の通りです

主な機能をいくつか紹介します

    スタートアップ: php が呼び出されたときの初期化操作
たとえば、CGI モードでは、すべての拡張機能がロードされ、起動時にモジュールの初期化が実行されます。

    shutdown: PHP がシャットダウンされたら作業を終了します

    activate: 初期化をリクエストします

    dectivate: リクエストの最後に作業を終了します

    ub_write: データの出力方法を指定します
たとえば、apache2handler メソッドでは、php が Apache の so として存在するため、その出力は Apache の ap_write 関数を呼び出し、CGI モードではシステムが write を呼び出します。

    sapi_error: エラー処理関数

    read_post: 投稿データを読み取る

    register_server_variables: $_SERVER に環境変数を登録します
この変数は通常、さまざまなプロトコル標準に従って登録されます。

5. PHPの実行プロセスとオペコード

まずはphpコードを実行するプロセスを見てみましょう。

図からわかるように、PHP は典型的な動的言語の実行プロセスを実装しています。コードの一部を取得した後、字句解析、構文解析、その他の段階を経て、ソース プログラムが命令 (オペコード) に変換され、その後 ZEND 仮想マシンはこれらの命令を順番に実行して操作を完了します。 Php 自体は C で実装されているため、最終的に呼び出される関数はすべて C の関数です。実際には、PHP は C で開発されたソフトウェアと考えることができます。

上記の説明から、PHP 実行の中核は 1 つずつ翻訳された命令、つまりオペコードであることがわかります

あなたオペコード

オペコードは、PHP プログラム実行の最も基本的な単位です。オペコードは 2 つのパラメータ (op1、op2)、戻り値、および処理関数で構成されます。 Php プログラムは最終的に一連のオペコード処理関数の順次実行に変換されます

いくつかの一般的な処理関数

ZEND_ASSIGN_SPEC_CV_CV_HANDLER: 変数の割り当て ($a=$b)

ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER:関数呼び出し

ZEND_CONCAT_SPEC_CV_CV_HANDLER: 文字列連結 $a.$b

ZEND_ADD_SPEC_CV_CONST_HANDLER: 加算演算 $a+2

ZEND_IS_EQUAL_SPEC_CV_CONST: 同等判定 $a==1

ZEND_IS_IDENTICAL_SPEC_CV_CONST: $a===1 に等しいと判断します

6. HashTable — コアデータ構造

HashTable は zend の中心的なデータ構造であり、php のほぼすべての一般的な関数を実装するために使用されます。さらに、関数シンボル テーブル、グローバル変数などの php 配列も zend 内で使用されます。ハッシュ テーブルに基づいて実行します。

PHP のハッシュ テーブルには次のような特徴があります:

  • 典型的なキー->値クエリをサポートします
  • 配列として使用できます
  • ノードの追加と削除は O(1) の複雑さです
  • キーは混合型をサポートします: 同時に関連付けられた数値の組み合わせのインデックス配列があります
  • 値は混合型をサポートします: array ("string",2332)
  • 線形トラバーサルのサポート: foreach など

Zend ハッシュ テーブルは、典型的なハッシュ テーブルのハッシュ構造を実装し、同時に二重リンク リストを追加することによって配列の順方向および逆方向の走査機能を提供します。その構造は以下の通りです

ハッシュ テーブルには、キー -> 値の形式のハッシュ構造と二重リンク リスト モードの両方があり、高速検索と線形トラバーサルをサポートするのに非常に便利であることがわかります。

  • ハッシュ構造

Zend のハッシュ構造は典型的なハッシュ テーブル モデルであり、リンク リストを通じて競合を解決します。 Zend のハッシュ テーブルは自己成長するデータ構造であり、ハッシュ テーブルがいっぱいになると動的に 2 倍に拡張され、要素の位置が変更されることに注意してください。初期サイズは8です。

さらに、キー->値の高速検索を実行する場合、zend 自体も空間を時間に交換することでプロセスを高速化するいくつかの最適化を行っています。たとえば、各要素で変数 nKeyLength を使用してキーの長さを識別し、迅速に決定します。

  • 二重リンクリスト

Zend ハッシュ テーブルは、リンク リスト構造による要素の線形走査を実装します。理論的には、走査には一方向リンク リストを使用するだけで十分です。二重リンク リストを使用する主な目的は、迅速に削除して走査を回避することです。

Zend ハッシュ テーブルは複合構造であり、配列として使用すると、一般的な連想配列をサポートし、連続したインデックス番号として使用したり、2 つを混合したりすることもできます。

  • PHP連想配列

連想配列は典型的な hash_table アプリケーションです。クエリプロセスは次のステップを経ます

プレーンプリントを表示しますか?
  1. getKeyHashValue h;  
  2. index = n & nTableMask;  
  3. バケット *p = arBucket[インデックス];  
  4. ながら (p) {
  5. if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
  6. Return p->data;     
  7. }  
  8. p=p->next;  
  9. }  
  10. 失敗を返す;  


コードからわかるように、これは一般的なハッシュ クエリ プロセスであり、検索を高速化するためにいくつかの高速判定が追加されています。

  • PHPのインデックス配列

インデックス配列は共通の配列であり、添字を介してアクセスされます。例: $arr[0]

Zend HashTable は内部で正規化されており、インデックス型のキーにもハッシュ値と nKeyLength (0) が割り当てられています。内部メンバー変数 nNextFreeElement は現在割り当てられている最大 ID であり、プッシュするたびに自動的に 1 ずつ増加します。

この正規化プロセスにより、PHP は結合性と非結合性の混合を実現できます

プッシュ操作の特殊性により、PHP 配列内のインデックス キーの順序は添え字のサイズではなく、プッシュの順序によって決まります。

たとえば、$arr[1] = 2;

double 型のキーの場合、Zend HashTable はそれらをインデックス キーとして扱います

7. PHP 変数

概要

  • Php は型付けが弱い言語であり、変数の型を厳密に区別しません。

  • Php では変数を宣言するときに型を指定する必要はありません。

  • Php は、プログラムの実行中に変数の型の暗黙的な変換を実行する場合があります。

  • 他の厳密に型指定された言語と同様に、プログラム内で明示的な型変換を実行することもできます。

  • Php変数は、単純型(int、string、bool)、コレクション型(配列リソースオブジェクト)、定数(const)に分類できます

  • 上記の変数はすべて、下部に同じ構造があります: zval

ズヴァル

Zval は Zend のもう 1 つの非常に重要なデータ構造であり、php 変数の識別と実装に使用されます。そのデータ構造は次のとおりです

Zval は主に 3 つの部分で構成されます:

1. type: 変数のタイプ (整数、文字列、配列など) を指定します

2. refcount&is_ref: 参照カウントの実装に使用されます (詳細は後ほど説明します)

3. 値: 変数の実際のデータを保存するコア部分

価値があります

Zvalue は、変数の実際のデータを保存するために使用されます。複数の型を格納する必要があるため、zvalue は共用体であり、弱い型付けが実装されています。

Php変数の型と実際のストレージの対応関係は以下の通りです

IS_LONG -> 左辺値

IS_DOUBLE ->dvalue

;

IS_ARRAY ->ht;

IS_STRING -> str

IS_RESOURCE -> 左辺値

参照カウント

参照カウントは、メモリのリサイクル、文字列操作などで広く使用されています。 Php の変数は、参照カウントの典型的なアプリケーションです

Zval の参照カウントは、メンバー変数 is_ref および ref_count によって実装されます。参照カウントを通じて、複数の変数が同じデータを共有できます。頻繁なコピーによる大量消費を避けてください

代入操作中、zend は変数を同じ zval および ref_count++ に指し、設定解除操作中は、対応する ref_count-1 を指します。破棄操作は、ref_count が 0 に減った場合にのみ実行されます

それが参照割り当ての場合、zend は is_ref を 1 に変更します

書きながらコピーしてください

Php 変数は、参照カウントを通じて変数の共有データを実現します。変数の 1 つの値を変更するとどうなるでしょうか。

変数を書き込もうとするときに、その変数が指す zval が複数の変数で共有されていることがわかると、Zend は ref_count が 1 の zval をコピーし、元の zval の refcount をデクリメントします。このプロセスは「zval 分離」と呼ばれます。 」。 zend は書き込み操作が発生したときにのみコピー操作を実行することがわかり、コピー オン ライト (コピー オン ライト) とも呼ばれます

参照変数の場合、要件は非参照型の要件と逆になります。1 つの変数を変更すると、バンドルされたすべての変数が変更されます。

整数型と浮動小数点型の変数

整数と浮動小数点数は PHP の基本的な型の 1 つであり、単純な変数でもあります。

整数と浮動小数点数の場合、対応する値は zvalue に直接格納されます。タイプはそれぞれlongとdoubleです。

zvalue 構造から、整数型の場合、C などの厳密に型指定された言語とは異なり、PHP では int、unsigned int、long、long long などの型が 1 つだけ存在することがわかります。整数、つまり長整数。このことから、php では整数の値の範囲はコンパイラのビット数によって決まり、固定されていないことがわかります。 浮動小数点数については、整数と同様に float と double の区別はなく、double のみが統一されます。

PHP で、整数の範囲が範囲外の場合はどうすればよいですか?
  • この場合、自動的に double 型に変換されてしまいますので、これが原因で起こるトリックが多いので注意が必要です。

文字列変数

整数と同様、文字変数も PHP の基本型であり単純な変数です

zvalue 構造から、PHP の文字列は、C++ の文字列と同様に、実際のデータへのポインターと長さ構造で構成されていることがわかります。

c とは異なり、長さは実際の変数で表されるため、その文字列はバイナリ データ (含む) にすることができます。

文字列操作を追加、変更、または追加すると、PHP はメモリを再割り当てして新しい文字列を生成します。

最後に、セキュリティ上の理由から、php は文字列を生成するときに最後に追加します。

一般的な文字列の結合方法と速度の比較

    次の 4 つの変数があるとします。
  • $strA='123'; $strB='456'; intB=456;
では、以下の文字列結合方法を比較して説明してみましょう

1. $res = $strA.$strB および $res = “$strA$strB”

この場合、zend はメモリの一部を再度割り当てて、それに応じて処理し、その速度は平均的です

2. $strA = $strA.$strB

これは最速です。zend はコピーの繰り返しを避けるために、現在の strA に基づいて直接再割り当てします

3. $res = $intA.$intB

暗黙的な形式変換が必要なため、この速度は遅くなりますが、プログラムを作成する際にはそれを回避するように注意する必要があります

4. $strA = sprintf (“%s%s”,$strA.$strB);

sprintf は PHP の言語構造ではないため、これは最も遅い方法になります。また、そのメカニズム自体が malloc であるため、フォーマットの識別と処理に多くの時間がかかります。ただし、sprintf メソッドは最も可読性が高く、実際には特定の状況に応じて柔軟に選択できます。

配列変数

前に述べたように、Php 配列は Zend HashTable を通じて自然に実装されます

foreach操作を実装するにはどうすればよいですか?

配列の foreach は、ハッシュテーブル内の二重リンク リストを走査することによって完了します。インデックス配列の場合、foreach を介した走査は for よりもはるかに効率的であり、キー→値を検索する必要がなくなります
  • Count オペレーションは、HashTable->NumOfElements, O(1) オペレーションを直接呼び出します
「123」のような文字列の場合、zend はそれを整数形式に変換します。 $arr[‘123’] と $arr[123] は同等です

リソースタイプ変数

これは PHP で最も複雑な変数であり、複合構造でもあります。

Php の zval は幅広いデータ型を表すことができますが、カスタム データ型を完全に記述するのは困難です。これらの複合構造を表現する効率的な方法がないため、それらに対して従来の演算子を使用する方法はありません。この問題を解決するには、

リソース

と呼ばれる本質的に任意の識別子 (ラベル) を介してポインターを参照するだけです。

zval (リソース) では、lval がリソースのアドレスを直接指すポインターとして使用されます。

リソースは任意の複合構造にすることができます。よく知られている mysqli、fsock、memcached などはすべてリソースです。

リソースを使用する

• 登録

  • カスタム データ型の場合は、それをリソースとして使用します。まず登録する必要があります。zend がグローバルに一意の識別子を割り当てます
  • • リソース変数を取得します

リソースについては、zend は実際のデータの id->hash_tale を維持します。リソースの場合、その ID のみが zval に記録されます。フェッチするときは、id を通じて hash_table 内の特定の値を見つけて返します
    • • リソースの破壊

    リソースのデータ型は多様です。 Zend 自体にはそれを破壊する方法はありません。したがって、ユーザーはリソースを登録する際に破棄機能を提供する必要があります。リソースの設定が解除されると、zend は対応する関数を呼び出して破棄を完了します。グローバルリソーステーブルからも削除してください。

    • 永続的なリソース

    リソースは、それを参照するすべての変数がスコープ外になった後だけでなく、リクエストが終了して新しいリクエストが行われた後でも、長期間存続できます。これらのリソースは、特に破棄されない限り、SAPI のライフサイクル全体を通して存続するため、永続リソース と呼ばれます。

    多くの場合、永続リソースによりパフォーマンスがある程度向上します。たとえば、一般的な mysql_pconnect では、永続リソースは pemalloc を通じてメモリを割り当て、リクエストが終了しても解放されないようにします。

    zend の場合、この 2 つ自体には区別がありません。

    Php変数のスコープ

    • Phpではローカル変数とグローバル変数はどのように実装されますか?

    リクエストの場合、PHP は常に 2 つのシンボル テーブル (symbol_table と active_symbol_table) を参照できます。そのうち前者はグローバル変数を維持するために使用されます。後者は、現在アクティブな変数シンボル テーブルを指すポインターです。プログラムが関数に入ると、zend はシンボル テーブル x をそれに割り当て、active_symbol_table を a に指します。このようにして、グローバル変数とローカル変数の区別が実現されます

    • 変数値を取得します

    PHP のシンボル テーブルは hash_table を通じて実装され、取得時に対応する zval がテーブルから検索され、その識別子に基づいて返されます。

      関数内でグローバル変数を使用する
    関数内で明示的に global を宣言することで、グローバル変数を使用できます。 active_symbol_tableのsymbol_tableに同名の変数への参照を作成します。symbol_tableに同名の変数が無い場合は先に作成されます

    YoungerChenさんのコラムより抜粋

    http://www.bkjia.com/PHPjc/478610.htmlwww.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/478610.html技術記事動的言語としての PHP はどのように実装され、その基礎となるメカニズムは何であり、どのような特徴があるのでしょうか? この記事では、PHP の設計概念、全体的な構造、およびコアとなるデータ構造を簡単に説明します...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。