1. ホーム
  2. Web プログラミング
  3. PHP プログラミング
  4. phpのヒント

PHPの変数代入の原理を深く理解する

2022-01-15 08:20:54

PHPにおける変数の割り当て

これは、おそらく多くの人が気にしないであろうタイトルです。しかし、値と参照の関係など、多くの人が混乱するほど基本的なことなのです。今日は、それについて詳しく説明します。

まず、変数の定義と値の代入は言うまでもありませんよね?

$a = 1;

$b = '2';

$c = [4, 5, 6];

$d = new stdClass();

4つの変数で、それぞれ整数、文字列、配列のオブジェクトを定義しています。私たちが日常的に扱うのは、この4つの型です。

そして、変数に値を代入する。

$a1 = $a;

$b1 = $b;

$c1 = $c;

$d1 = $d;

最初の3つの代入は通常の代入、すなわち仕様のコピーであることに注意してください。a1を変更しても、$aは変わりません。a1は私たちの値を保持する新しく開かれたメモリ空間です。つまり、同じ値を持つが、メモリーアドレスは異なる。これは、互いに何の関係もない2つのそっくりさんに過ぎないのです。

しかし、$d1と$dは違います。同じ値であるだけでなく、同じメモリアドレスを持っています。このような状況を参照代入と呼びます。d1が変化すると、$d2も変化します。

いわば、参照代入は、Windowsでは元の変数へのショートカットを、Linuxではソフトリンクを作るのです。

具体的な例で説明すると、まず共通の値を代入する場合

// Common assignment

$v = '1';

$c = $v;

$c = '2';

echo $v, PHP_EOL; // '1'

// Arrays are also normal assignments

$arr1 = [1,2,3];

$arr2 = $arr1;

$arr2[1] = 5;

print_r($arr1); // [1, 2, 3]

cは$vの値に影響を与えません。$arr2は5から2番目の数字である添え字1を修正し、もちろん$arr1には何の影響も与えません。

オブジェクト形式での参照代入はどうでしょうか?

// Objects are assigned by reference

class A {

    public $name = 'I am A';

}

$a = new A();

$b = $a;

echo $a->name, PHP_EOL; // 'I am A'

echo $b->name, PHP_EOL; // 'I am A'

$b->name = 'I am B';

echo $a->name, PHP_EOL; // 'I am B'

予想通り、$bがname属性の内容を変更した後、$aの中の名前も$bが変更したものになる。

この場合、オブジェクトが参照渡しでなければ、1つはプロトタイプパターンである__clone()を使って、自分自身のコピーを作ることである。2つは、外からチャントを再新する。

// Use cloning to solve the reference passing problem

class Child{

    public $name = 'I am A1's subordinate';

}

class A1 {

    public $name = 'I am A';

    public $child;

    function __construct(){

        $this->child = new Child();

    }

    function __clone(){

        $this->name = $this->name;

        // new or use Child's clone either

        // $this->child = new Child();

        $this->child = clone $this->child;

    }

}

a1 = new A1();

echo $a1->name, PHP_EOL; // output the original content of a1

echo $a1->child->name, PHP_EOL;

$b1 = $a1;

echo $b1->name, PHP_EOL; // b1 is now also the content of a1

echo $b1->child->name, PHP_EOL;

$b1->name = 'I am B1'; // b1 modifies the content

$b1->child->name = 'I am B1's subordinate';

echo $a1->name, PHP_EOL; // a1 becomes the content of b1

echo $a1->child->name, PHP_EOL;

// Use __clone

$b2 = clone $b1; // b2 clones b1

$b2->name = 'I am B2'; // b2 modifies the content

$b2->child->name = 'I am B2's subordinate';

echo $b1->name, PHP_EOL; // b1 doesn't become what b2 modifies

echo $b1->child->name, PHP_EOL;

echo $b2->name, PHP_EOL; // b2 modified content is fine, b1, b2 is not a cargo anymore

echo $b2->child->name, PHP_EOL;

オブジェクト参照の部分は、本当に混乱することがあります。特に、内部プロパティや他のオブジェクトへの様々な参照を持つ、より複雑なオブジェクトになるとなおさらです。この場合、参照の割り当てが問題を起こさないかどうか、必ず再確認してください。もし問題を起こすようなら、新しいオブジェクトやクローン技術を使って、参照の問題に対処してください。

最後に、簡単に説明すると、参照変数の代入は、メソッドに参照パラメータを渡すのと同じで、&の記号を使うだけです!

// Assigning by reference

$b = &$v;

$b = '3';

echo $v, PHP_EOL;

今日、私たちはPHPの代入について、特に通常の代入と参照代入について学び、理解しました。次回、コードやフレームワークを見るときに、他の人がこの2種類の代入をどのように柔軟に使っているかに注目し、また、自分が書いたバグをこの2つの方法を使って変形してみることができますよ。

<ブロッククオート

テストコード

https://github.com/zhangyue0503/dev-blog/blob/master/php/201910/source/PHP%E7%9A%84%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC.php

参考文献

https://www.php.net/manual/zh/language.variables.basics.php

この記事では、PHPの変数代入を深く理解するための原理について紹介します。PHPの変数代入に関するより詳しい内容は、BinaryDevelopの過去の記事を検索するか、以下の関連記事を引き続き閲覧してください!今後、BinaryDevelopをよりサポートしていただけると幸いです。