PHP_PHP チュートリアルでグローバル変数を使用するいくつかの方法を分析する

WBOY
リリース: 2016-07-21 15:04:16
オリジナル
847 人が閲覧しました

はじめに
新しい大規模な PHP プログラムを開発する場合でも、一部のデータはコードのさまざまな部分で使用する必要があるため、必然的にグローバル データを使用することになります。一般的なグローバル データには、プログラム設定クラス、データベース接続クラス、ユーザー情報などが含まれます。このデータをグローバル データにする方法は数多くありますが、最も一般的に使用される方法は、「global」キーワード宣言を使用することです。これについては、この記事の後半で詳しく説明します。
「global」キーワードを使用してグローバル データを宣言する唯一の欠点は、これが実際には非常に不適切なプログラミング方法であり、グローバル データによってコードが分離されるため、後でプログラムでより大きな問題が発生することがよくあることです。相互にリンクされているため、コードの一部を変更すると、他の部分に問題が発生する可能性があります。したがって、コード内に多くのグローバル変数がある場合、プログラム全体の保守が困難になります。

この記事では、さまざまな手法や設計パターンを通じてこのグローバル変数の問題を防ぐ方法を説明します。もちろん、最初にグローバル データに「global」キーワードを使用する方法とその仕組みを見てみましょう。

グローバル変数と「global」キーワードを使用する
PHP はデフォルトでいくつかの「スーパーグローバル」変数を定義します。これらは自動的にグローバル化され、$_GET や $_REQUEST など、プログラム内のどこからでも呼び出すことができます。通常、これらの変数はデータまたはその他の外部データから取得されますが、これらの変数は基本的に書き込み可能ではないため、通常は使用しても問題は発生しません。

ただし、独自のグローバル変数を使用することもできます。キーワード「global」を使用すると、グローバル データを関数のローカル スコープにインポートできます。 「変数の使用範囲」がわからない場合は、PHP マニュアルの該当する説明を参照してください。
以下は、「global」キーワードを使用したデモの例です:

コードをコピーします コードは次のとおりです:

$my_var = 'Hello World';
test_global( );
function test_global() {
// 現在はローカル スコープ内です
// $my_var 変数は存在しません
// エラーが生成されます: "未定義の変数: my_var"
echo $my_var;
// 次に、 variable
global $ my_var;
// Works:
echo $my_var;
}
?>

上の例でわかるように、「global」キーワードはグローバル変数をインポートするために使用されます。うまく機能し、シンプルであるように見えますが、グローバル データを定義するために「global」キーワードを使用することをなぜ心配するのでしょうか?
その理由は 3 つあります:

1. コードの再利用はほぼ不可能です。
関数がグローバル変数に依存している場合、この関数を異なる環境で使用することはほぼ不可能です。もう 1 つの問題は、この関数を抽出して他のコードで使用できないことです。

2. デバッグと問題の解決は非常に困難です。
グローバル変数の追跡は、非グローバル変数の追跡よりもはるかに困難です。グローバル変数は、不明瞭なインクルード ファイルで再定義されている可能性があり、非常に優れたプログラム エディタ (または IDE) を使用していても、問題を発見するまでに数時間かかる場合があります。

3. これらのコードを理解するのは非常に困難です。
グローバル変数がどこから来て何に使われるのかを理解するのは困難です。開発プロセス中はすべてのグローバル変数を知っているかもしれませんが、約 1 年後には、少なくとも一部のグローバル変数を忘れてしまう可能性があります。その時点で、非常に多くのグローバル変数を使用したことを後悔するでしょう。
では、グローバル変数を使用しない場合は何を使用すればよいでしょうか?以下にいくつかの解決策を見てみましょう。
関数パラメータの使用
グローバル変数の使用をやめる 1 つの方法は、以下に示すように、変数をパラメータとして関数に渡すことです:

コードをコピーします コードは次のとおりです:

< ;?php
$var = 'Hello World';
test ($var);
function test($var) {
echo $var;
}
?>

グローバル変数を渡すだけの場合、これは非常に優れた、または優れたソリューションです。しかし、多くの値を渡したい場合はどうすればよいでしょうか?
たとえば、データベース クラス、プログラム設定クラス、ユーザー クラスを使用する場合。私たちのコードでは、これら 3 つのクラスはすべてのコンポーネントで使用されるため、これらをすべてのコンポーネントに渡す必要があります。関数パラメーター メソッドを使用する場合は、これを行う必要があります。
コードをコピーします。 コードは次のとおりです。
$db = new DBConnection
$settings = new Settings_XML;
$user = 新しいユーザー;
test($db, $settings, $user);
function test(&$db, &$settings, &$user) {
// 何かをします
}
?>


明らかに、これは価値がありません。追加する新しいオブジェクトができたら、各関数に関数パラメーターをもう 1 つ追加する必要があります。したがって、別の方法を使用してそれを解決する必要があります。

シングルトンを使用する
関数パラメーターの問題を解決する 1 つの方法は、シングルトンを使用して関数パラメーターを置き換えることです。シングルトンは、一度だけインスタンス化できるオブジェクトの特別なクラスであり、オブジェクトのインターフェイスを返す静的メソッドが含まれています。次の例は、簡単なシングルトンの構築方法を示しています:
コードをコピーします
コードは次のとおりです: // DBConnection のインスタンスを取得します
$db =& DBConnection:: getInstance( );
// オブジェクトのユーザー プロパティを設定します
$db->user = 'sa';
// 2 番目の変数 (同じインスタンスを指す) を設定します
$sec =& DBConnection::getInstance();
/ / 'sa' を出力する必要があります
echo $second->user;
Class DBConnection {
var $user;
function &getInstance() {
static $me;
if (is_object($me) == true) {
$me を返す;
$me; }
}
?>


上記の例の最も重要な部分は、関数 getInstance() です。この関数は、静的変数 $me を使用して DBConnection クラスのインスタンスが 1 つだけ存在することを確認して、このクラスのインスタンスを返します。
シングルトンを使用する利点は、オブジェクトを明示的に渡す必要がなく、次のように getInstance() メソッドを使用するだけでオブジェクトを取得できることです:



コードをコピーします

コードは次のとおりです:


function test() {
$db = DBConnection::getInstance();
// オブジェクトを使って何かをします
}
?>しかし、欠点もいくつかありますシングルトンを使用する場合。まず、クラス内の複数のオブジェクトをグローバル化する必要がある場合はどうすればよいでしょうか?シングルトンを使用しているため、これは不可能です(名前がシングルトンであるため)。もう 1 つの問題は、シングルトンを個別のテストを使用してテストできないことです。スタック全体を導入しない限り、これは完全に不可能です。これは明らかに見たくないことです。これが、シングルトンが理想的なソリューションではない主な理由です。
登録パターン

コード内のすべてのコンポーネント (翻訳者注: グローバル オブジェクトまたはデータ) で一部のオブジェクトを利用できるようにする最良の方法は、中央のコンテナ オブジェクトを使用してすべてのオブジェクトを含めることです。通常、このコンテナ オブジェクトはレジストラと呼ばれます。非常に柔軟で非常にシンプルです。単純なレジストラ オブジェクトは次のようになります:



コードをコピーします
コードは次のとおりです:


Class Registry {
var $_objects = array(); function set($name, & $object) {
use using using using through ;

登録オブジェクトを使用する最初のステップは、set() メソッドを使用してオブジェクトを登録することです:
コードをコピーします コードは次のとおりです:

$db = new DBConnection ;
$settings = 新しい Settings_XML;
$user = 新しいユーザー;
// オブジェクトを登録します
$registry =& 新しいレジストリ;
$registry->set ('db', $db);
$registry-> set ('settings', $settings);
$registry->set ('user', $user);
?>

register オブジェクトにすべてのオブジェクトが保持されたので、この register オブジェクトを渡す必要があります(3 つのオブジェクトを別々に渡すのではなく) 関数に追加します。以下の例を見てください:
コードをコピーします コードは次のとおりです:

function test(&$registry) {
$db =& $registry->get(' db');
$settings =& $registry->get('settings');
$user =& $registry->get('user');
// オブジェクトを使って何かをします
}
? >

他のメソッドと比較して、レジスタの大きな改善点は、コードに新しいオブジェクトを追加する必要があるときに、すべてを変更する必要がなくなったことです (翻訳者注: コードを使用するプログラム内のすべてを指します)グローバル オブジェクトの) の場合、レジスタに新しいオブジェクトを登録するだけでよく、その後、そのオブジェクト (翻訳者注: 新しく登録されたオブジェクト) をすべてのコンポーネントですぐに呼び出すことができます。

レジスタを使いやすくするために、レジスタの呼び出しをシングルトン モードに変更しました (翻訳者注: 上記の関数転送は使用しないでください)。プログラム内で使用する必要があるのはレジスター 1 つだけであるため、シングルトン パターンはこのタスクに非常に適しています。次のように register クラスに新しいメソッドを追加します:
コードをコピーします コードは次のとおりです:

function &getInstance() {
static $me;
if (is_object($me) ) == true) {
「」""""" """"
コードをコピーします

コードは次のとおりです:


$db = new DBConnection;
$settings = new Settings_XML;
$user = new User;
// オブジェクトを登録します$registry =& Registry::getInstance ();$registry->set ('db', $db);$registry-> set ('settings', $settings);$registry->set ('user', $user) ;
function test() {
$registry =& Registry::getInstance();
$db =& $ registry->get('db');
$settings =& $registry->get('settings ');
$user =& $registry->get('user');
// 何かをするオブジェクトを使用して
}
?>


ご覧のとおり、プライベートなものを置く必要はありません。すべてが関数に渡され、「global」キーワードを使用する必要はありません。したがって、レジストラ パターンはこの問題に対する理想的な解決策であり、非常に柔軟です。


リクエストラッパー

レジストラは「global」キーワードを完全に冗長にしましたが、コードには依然として 1 種類のグローバル変数が存在します。それは、変数 $_POST、$_GET などのスーパー グローバル変数です。これらの変数は非常に標準的なものであり、問​​題なく動作するはずですが、場合によっては、レジスタを使用して変数をカプセル化する必要がある場合もあります。
簡単な解決策は、これらの変数を取得するためのインターフェイスを提供するクラスを作成することです。これはよく「リクエスト ラッパー」と呼ばれます。簡単な例を次に示します。


コードをコピーします。 コードは次のとおりです。


Class Request {
var $_request = array() ; 関数 Request() {
‐ ‐ ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ ?> ;

上記の例は単純なデモンストレーションです。もちろん、リクエスト ラッパーでは他の多くのこと (データの自動フィルタリング、デフォルト値の提供など) を行うことができます。
次のコードは、リクエスト ラッパーを呼び出す方法を示しています:
コードをコピー コードは次のとおりです:

$request = new Request;
// Register object
$registry =&レジストリ: :getInstance();
$registry->set ('request', &$request);
test();
function test() {
$registry =& Registry::getInstance();
$request =& $registry->get ('request');
// 'name' クエリ文字列を出力します。通常は $_GET['name'] になります
echo htmlentities($request->get('name' )) ;
}
?>

ご覧のとおり、現在はグローバル変数に依存しなくなり、これらの関数をグローバル変数から完全に遠ざけています。

結論
この記事では、コードからグローバル変数を根本的に削除し、それらを適切な関数と変数に置き換える方法を説明しました。登録パターンは、非常に柔軟性があり、コードが混乱するのを防ぐため、私のお気に入りのデザイン パターンの 1 つです。
また、レジストラ オブジェクトを渡すには、シングルトン パターンの代わりに関数パラメーターを使用することをお勧めします。シングルトンを使用する方が簡単ですが、後で問題が発生する可能性があり、関数のパラメーターを渡すことも理解しやすいです。

www.bkjia.com本当http://www.bkjia.com/PHPjc/327793.html技術記事はじめに 新しい大規模な PHP プログラムを開発する場合でも、コードのさまざまな部分を使用するために一部のデータが必要になるため、必然的にグローバル データを使用することになります。一般的な全体像...
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート