ホームページ  >  記事  >  バックエンド開発  >  PHP引用の詳細な説明 – 落とし穴と魔法の使い方

PHP引用の詳細な説明 – 落とし穴と魔法の使い方

步履不停
步履不停オリジナル
2019-06-21 15:18:133093ブラウズ

PHP引用の詳細な説明 – 落とし穴と魔法の使い方

最近、「PHP リファレンス」というトピックに注目しており、詳細な記事をたくさん読み、PHP の「リファレンス」についての理解が深まりました。

0x00

まず次のコードを見てください:

$foo['hello'] = '0';
$bar = &$foo['hello']; // 引用!
$tipi = $foo;
$tipi['hello'] = '1';

print_r($foo);

Q: 出力 0 ですか、それとも出力 1 ですか?答えは 1 です。

原理は何ですか?

PHP カーネルは、変数を保存するために zval 構造体を使用します。PHP コードでは、xdebug_debug_zval 関数を使用して確認します。

上記のコードを変更します:

$foo['hello'] = '0';

xdebug_debug_zval('foo');
$bar = &$foo['hello']; // 引用!
xdebug_debug_zval('foo');

$tipi = $foo;
$tipi['hello'] = '1';

print_r($foo);

出力は次のようになります:

foo: (refcount=1, is_ref=0)=array ('hello' => (refcount=1, is_ref=0)='0')
foo: (refcount=1, is_ref=0)=array ('hello' => (refcount=2, is_ref=1)='0')

$foo['hello'] 非参照変数から(is_ref= 0) は参照変数 (is_ref=1) となり、参照数は refcount=2 となります。 ######どうしてこれなの?

PHP によると: 引用符は何をするのか - マニュアル

の説明:

$a =& $b;
これ$a と $b が同じ変数を指すことを意味します。ここでは

$a と $b はまったく同じです。$a が $b を指しているわけではなく、$a が $b を指しているわけではなく、$a と $b が同じ場所を指しているということです。

この例と組み合わせると、つまり

$bar = &$foo['hello'];
が実行されるとき、

$bar$foo['hello'] はすべて「参照変数」になり、「同じ場所を指します」。 次に、この配列をコピーすると、$tipi['hello'] = '1';

が実行されるときに、その

hello 要素の参照もコピーされます。の場合、tipi['hello']$foo['hello']$bar が指す「同じ場所」が変更されます。 したがって、$foo['hello']

の値は当然

1 になります。 0x01

少し詳細なリファレンスを持っている PHPer は、次の構文を試してみるとよいでしょう:

for ($list as &$value) {
    $value = 'foo';
}

PHP は制御構造の後に変数をリサイクルしないため、ここではリサイクルしません。ここで説明してください; つまり、今のピットは実際に拡張することができます。

$foo['hello'] = '0';
$foo['world'] = 'A';
foreach($foo as &$value) { // 引用!
    // Do nothing.
}
$tipi = $foo;
$tipi['hello'] = '1';
$tipi['world'] = 'B';
print_r($foo);
ここでの出力は次のとおりです。

Array
(
    [hello] => 0
    [world] => B
)

hello

は通常ですが、

worldB に変更されます。理由は、xdebug_debug_zval 関数を使用して自分で調べることができます。 したがって、気軽に unset($value);

を行うのは良い習慣です。

0x02

実際、引用は落とし穴ばかりではありません。まだまだ大きなメリットがあります。

例:

$catList = [
    '1' => ['id' => 1, 'name' => '颜色', 'parent_id' => 0],
    '2' => ['id' => 2, 'name' => '规格', 'parent_id' => 0],
    '3' => ['id' => 3, 'name' => '白色', 'parent_id' => 1],
    '4' => ['id' => 4, 'name' => '黑色', 'parent_id' => 1],
    '5' => ['id' => 5, 'name' => '大', 'parent_id' => 2],
    '6' => ['id' => 6, 'name' => '小', 'parent_id' => 2],
    '7' => ['id' => 7, 'name' => '黄色', 'parent_id' => 1],
];
上記のシーケンス テーブルを階層ツリーに変換するにはどうすればよいですか?

以前、あるいは通常、私たちが最初に考えたのは再帰的バックトラッキングでした。

ただし、PHP の参照機能を使用すると、時間計算量を

O(n)

に減らすことができます。

$treeData = [];
foreach ($catList as $item) {
    if (isset($catList[$item['parent_id']]) && !empty($catList[$item['parent_id']])) {
        // 子分类
        $catList[$item['parent_id']]['children'][] = &$catList[$item['id']];
    } else {
        // 一级分类
        $treeData[] = &$catList[$item['id']];
    }
}

var_export($treeData);
PHP 関連の技術記事の詳細については、

PHP チュートリアル 列にアクセスして学習してください。

以上がPHP引用の詳細な説明 – 落とし穴と魔法の使い方の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。