1

多次元配列があり、一部の要素はオブジェクトです。1 つはすべての文字列値とオブジェクト プロパティが esc() 関数を介して渡されたもので、もう 1 つは変更されていない元の配列です。

次のコードがあるとします。

$raw = $data;
echo $raw['obj']->description; // Prints '< >Test Desc'

array_walk_recursive($data, function (&$item, $key){
   if(is_string($item)) {
      $item = esc($item);
   } elseif(is_object($item)) {
      foreach ($item as $property => $value)  {
          if(is_string($value)) {
              $item->$property = esc($value);
          }
      }
   }
});

echo $data['obj']->description; // Prints '&lt; &gt;Test Desc' - Correct
echo $raw['obj']->description; // Prints '&lt; &gt;Test Desc' - Incorrect

$raw は完全に変更されておらず、$data は esc() によって処理されているはずです。これは、オブジェクト プロパティを除いて当てはまります。何らかの理由で $raw のオブジェクトも変更され、2 つのecho行が異なる値を出力するようになっています。これはなぜですか?

4

3 に答える 3

3

PHP 5 オブジェクトは常に参照渡しであるためです。

オブジェクトを実際にコピーするには、オブジェクトを「複製」する必要があります。

詳細については、 http://php.net/manual/en/language.oop5.references.phpを参照してください。

于 2012-11-22T13:37:57.590 に答える
1

PHPの内部のpass-object-by-referenceがここで機能しています。

一言で言えば、PHPは自然にオブジェクトを参照によって渡します。これには配列メンバーが含まれます。これを証明する必要がある場合は、次のスクリプトを試してください。

<?php $arr = array(new stdClass()); var_dump($arr[0]); $arr2 = $arr; var_dump($arr[0]); ?>

object(stdClass)[1]どちらの場合も出力はになります。

使用するソリューションがいくつかあります。たとえば、cloneオブジェクトの演算子を利用できます。配列の構造を知っているなら、これは簡単です。そうしないと、PHPが配列を実行できないため、問題が発生しますclone(したがって、再帰的に配列をウォークする必要があります)。他のすべてのソリューションには、編集する前にオブジェクトデータを複製することが含まれます。

于 2012-11-22T13:43:03.513 に答える
1

PHP では、オブジェクトは参照によって渡されます。これは、オブジェクト$aを変数に割り当てると、と$bの両方が同じオブジェクトを指すことを意味します。これについては、オブジェクトと参照のマニュアル ページで詳しく説明しています。$a$b

演算子を使用してclone、オブジェクトのクローンを実際に作成できます。

$b = clone $a;

ただし、これはオブジェクトに対してのみ機能するため、オブジェクトに使用する配列のコピーを再帰的に作成する必要がありcloneます。

于 2012-11-22T13:39:57.083 に答える