現実の状況で効果的な PHP コードを開発する方法に関するこのシリーズのパート 3 では、Amol Hatwar が、パフォーマンスや管理性をあまり犠牲にすることなく使用できる最も効率的な関数を構築する方法について説明します。著者は再利用可能な関数の作成に焦点を当て、このタスクに関連する最も一般的な問題のいくつかを回避する方法を示します。 おかえり。このシリーズのパート 1 では、いくつかの基本的な PHP 設計ルールについて説明し、安全でシンプル、プラットフォームに依存しない、高速なコードを作成する方法を示しました。パート 2 では、変数を紹介し、PHP コーディングでの変数の使用法 (良い習慣と悪い習慣) について説明しました。 この記事では、PHP で関数を賢く使用する方法を学びます。どの高級プログラミング言語でも、プログラマは関数を定義できます。PHP も例外ではありません。唯一の違いは、関数の戻り値の型を気にする必要がないことです。 ドリルダウン関数は次の目的で使用できます。 複数行のコードを 1 つのステートメントにカプセル化します。 コードを簡素化します。 最も重要なことは、アプリケーションを小規模なアプリケーションの調整された製品として扱うことです。 C/C++ などのコンパイル言語から PHP に来た開発者にとって、PHP のパフォーマンス レベルは驚くべきものです。ユーザー定義関数は、CPU とメモリのリソースを使用するという点で非常に高価です。これは主に、PHP が解釈され、型付けが緩いためです。 ラッパーかどうか 単純に関数の名前が気に入らないという理由で、使用するすべての関数をラップする開発者もいますが、ラッパーの使用をまったく好まない開発者もいます。 既存の機能を追加または補足せずに既存の PHP 関数をラップすることは、まったく受け入れられません。このような名前変更された関数は、サイズと実行時間の増加に加えて、管理上の悪夢を引き起こす可能性があります。 コード内のインライン関数は、不可解なコードを引き起こし、さらに大きな管理上の惨事につながる可能性があります。これを行うことの唯一の利点は、コードが高速になることです。 より賢いアプローチは、コードを複数回使用する必要があり、達成したいタスクに使用できる組み込み PHP 関数がない場合にのみ関数を定義することです。名前を変更するか、必要な場合にのみ制限付きで使用するかを選択できます。 図 1 のグラフは、使用する関数の数と管理性と速度の関係を大まかに示しています。 (数値は個人とチームの能力に依存するため、ここでは単位を指定しません。この関係を視覚化することが重要です。) 図 1. 管理性/速度と関数の数 関数の名前付け このシリーズで行ったように、記事 第 2 部 (「参考文献」を参照) で述べたように、効果的なコード管理には、常に共通の命名規則を使用することが不可欠です。 考慮すべき他の 2 つのプラクティスは次のとおりです。 関数が何を行うかについての良いヒントを与える名前を選択してください。 パッケージまたはモジュールを示すプレフィックスを使用します。 ユーザー管理関数を含む user という名前のモジュールがあると仮定すると、ユーザーが現在オンラインかどうかを確認する関数には、 usr_is_online() や usrIsOnline() などの関数名が適しています。 上記の名前を is_online_checker() のような関数名と比較してください。結論としては、関数は常に何かを行うため、名詞を使用するよりも動詞を使用する方が良いということです。 パラメータはいくつ? おそらく、すでに構築された関数を使用することになるでしょう。そうでない場合でも、コードのスコープを最大化したい場合があります。これを行うには、あなたと他の開発者が使いやすい機能の開発を続ける必要があります。あいまいで理解しにくいパラメーターを受け取る関数を使いたがる人はいないため、使いやすい関数を作成してください。 関数の目的を説明する名前を選択する (そして関数が受け取る引数の数を減らす) ことは、使いやすさを確保する良い方法です。パラメータの数を表すマジックナンバーは何ですか?私の意見では、パラメーターが 3 つを超えると関数を覚えにくくなります。多数のパラメータを持つ複雑な関数は、ほとんどの場合、より単純な関数に分割できます。 間に合わせの関数を使いたがる人はいません。 適切な関数を作成する HTML ドキュメントをブラウザに表示する前に、そのドキュメントのタイトルを設定するとします。タイトルは
... タグの間にあるすべてです。 title タグとmeta タグを設定するとします。 setHeader(title, name, value) 関数を使用してすべての作業を行う代わりに、setTitle(title) と setMeta(name, value) を使用して各作業を個別に実行する方が良い解決策となります。このスキームは、タイトル タグとメタ タグを互いに独立して設定します。 さらに考えると、タイトルにはタイトル タグを 1 つだけ含めることができますが、複数のメタ タグを含めることもできます。複数のメタ タグを設定する必要がある場合は、コードで setMeta() を複数回呼び出す必要があります。この場合、より良い解決策は、名前と値のペアの 2 次元配列を setMeta() に渡し、関数がその配列をループするようにすることです。すべてを同時に実行します。 一般に、このような同時機能が望ましいです。処理する必要があるすべてのデータを指定して関数を 1 回呼び出すことは、関数を複数回呼び出してデータを段階的に供給するよりも常に優れています。関数を作成するときの主な考え方は、他のコードからの関数への呼び出しを最小限に抑えることです。 これによると、setHeader() ソリューションは実際には良いアイデアではありません。明らかに、setHeader() を setHeader(title, array) にリファクタリングできますが、タイトル タグとメタ タグを互いに独立して設定する機能が失われることも考慮する必要があります。さらに、実際の環境では、タイトルには、タイトルタグとメタタグだけでなく、複数のタグが含まれる場合があります。さらにマークアップを追加する必要がある場合は、setHeader() とそれに依存する他のすべてのコードを変更する必要があります。後者の場合は、関数をもう 1 つ作成するだけです。 次の方程式はすべてのプログラミング言語に当てはまります: 覚えやすい名前 + 明確な引数 + 速度と効率 = すべてのプログラミング言語で優れた関数 階層化アプローチで関数を調整する 関数が単独で存在することはほとんどありません。これらは他の機能と連携してデータを交換および処理し、タスクを完了します。これらの関数またはモジュールのグループは再利用できる必要があるため、同じグループまたはモジュール内の他の関数と適切に動作する関数を作成することが重要です。 架空のページ構築例を続けてみましょう。ここで、このモジュールの役割は、HTML を使用してページを構築することです。 (この例の目的は、再利用性を高めながら関数や関数のグループがどのように簡単に連携できるかを説明することだけなので、ここでは詳細とコードを省略しましょう。) 組み込みの PHP 関数から始めて、抽象的なものを構築できます。関数を使用して、基本的なニーズを処理するさらに多くの関数を作成し、次にこれらの関数を順番に使用してアプリケーション固有の関数を構築します。図 2 は、これがどのように機能するかを示しています。 図 2. 階層化された関数 これで、ページがメモリ内に構築され、完成したページがブラウザに送信されます。 メモリ内にページを構築すると、2 つの大きな利点があります。 独自のスクリプトを使用して完成したページをキャッシュできる。 ページが正常に構築されない場合は、中途半端なページを破棄して、ブラウザにエラー ページを表示できます。 これで、ユーザーにはエラー メッセージを含むレポートがページ上に表示されなくなります。 ほとんどのページの構造に応じて、ページの構成要素を次の機能を実行する関数に分割する必要があります。 トップ バーの描画 ナビゲーション バーの描画 コンテンツの表示 脚注の追加 次の機能を実行する関数も必要です。 ページのキャッシュページがキャッシュされているかどうかを確認します。ページがすでにキャッシュされている場合は、それを pagebuilder モジュールと呼びます。 ページ ビルダー モジュールは、データベースにクエリを実行することによってその作業を実行します。データベースは PHP の外部にあるため、データベース抽象化モジュールを使用します。このモジュールの役割は、PHP のさまざまなベンダー固有のデータベース関数に同種のインターフェイスを提供することです。このモジュールの重要な関数は、データベースに接続する関数、データベースにクエリを実行する関数、クエリ結果を提供する関数です。 サイト全体の検索エンジンも実装したいとします。このモジュールは、特定のキーワードまたはキーワードのセットに関連するドキュメントをサイト内で検索し、検索文字列の関連性またはその文字列の出現回数に基づいて結果を表示する役割を果たします。このモジュールは、監査目的で検索のログも記録したい場合に、データベース抽象化モジュールと一緒に使用されます。 ユーザーからの入力を受け入れることに注意してください。悪意があると思われるコンテンツを画面に表示し、破棄する必要があります。これには、ユーザーがフォームを通じて送信したデータを検証する別のモジュールが必要です。 ここまでで、私が話している概念については大体理解できたはずです。最も中心となる機能は論理モジュールに分割する必要があり、それらのタスクを実行するには、アプリケーションはこれらのモジュールによって提供される関数を使用する必要があります。 この階層化アプローチを使用すると、単純なページ構築レンダリング アプリケーションは図 3 のようになります。 図 3. 階層化されたページ構築アプリケーション この例では、コア モジュールとアプリケーションを処理するモジュールの間に階層がないことに注意してください。つまり、コア モジュールは、抽象モジュールまたはその下の層で宣言された関数から関数を呼び出して宣言できますが、アプリケーション コードではそれができない場合があります。アプリケーション コードが低レベル関数によって「汚染」されている場合、またはカプセル化されている場合、アプリケーション コード内で関数を宣言しないでください。低レベルの関数のみを使用できます。これはより高速な方法であることが判明しました。 関数のテクニック 関数の使用方法と作成方法を理解したところで、いくつかの一般的なテクニックを検討してみましょう。 参照の使用 簡単に言えば、参照は C 言語のポインタのようなものです。唯一の違いは、PHP では、C のように逆参照するために * 演算子を使用する必要がないことです。これらは、変数、配列、またはオブジェクトのエイリアスと考えることができます。何をしても、エイリアスは実際の変数に影響を与えます。 リスト 1 に例を示します。 リスト 1. 変数参照 引数が関数に渡されると、関数は引数のコピーを受け取ります。パラメータに加えた変更は、関数が返されるとすぐに失われます。パラメータを直接変更したい場合、これは問題になる可能性があります。リスト 2 は、この問題を説明する例を示しています。 リスト 2. 関数に引数を渡すときの問題 $myNum を直接変更したいのですが、これは $myNum への参照をhalf() 関数に渡すことで簡単に行うことができます。ただし、これは良い習慣ではないことに注意してください。コードを使用する開発者は、使用された参照を追跡する必要があります。これにより、誤ってエラーが広がる可能性があります。機能の使いやすさにも影響します。 より良い方法は、関数宣言で参照を直接使用することです。この例では、half($num) の代わりにhalf(&$num) を使用します。このように、参照を覚えておけば、関数にパラメーターを渡すことを覚えておく必要がなくなります。 PHP は舞台裏でいくつかのことを処理します。新しい PHP バージョン (および 4.0 以降のバージョン) では、呼び出し時の参照による受け渡しが非推奨となり、いずれにしても警告が発行されます。 (ここにいくつかの提案があります: 以前のバージョンの PHP 用に書かれたコードを使用している場合は、php.ini ファイルを変更して PHP の動作を変更するよりも、コードを更新することをお勧めします。) 関数呼び出し間で変数を保持するには、多くの場合、メンテナンスが必要になります。関数呼び出し間の変数値。グローバル変数も使用できますが、変数は非常に壊れやすいため、他の関数によって破損する可能性があります。変数を関数に対してローカルにして、その値を保持する必要があります。 static キーワードを使用するのが良い解決策です。デバッガが使用できないときに実行されたユーザー定義関数の数をカウントしたい場合に、この方法をよく使用します。すべての関数を変更し (もちろん自動スクリプトを使用)、関数本体の最初の行にカウント作業を行う関数の呼び出しを追加しました。リスト 3 では、この関数について説明します。 リスト 3. ユーザー定義関数のカウント function funcCount() { static $count = 0; return $count++ } スクリプトが完了する直前に funcCount() を呼び出して変数を収集します