「リフレクション」を使用せずにオブジェクトのすべてのプロパティにアクセスする方法

オブジェクトのすべてのプロパティにアクセスしても、インターフェースを変更しないのはなぜですか? たとえば、シリアル化を記述するために。 または、httpを使用して受け入れ可能な形式でオブジェクトを渡します。 または他の何かのために。



実験のために簡単なクラスを取りましょう。



class aClass { protected $protected_property = 'protected_value'; private $private_property = 'private_value'; public $public_property = 'public_value'; } $an_object = new aClass; var_dump($an_object); // object(aClass)#1 (3) { // ["protected_property":protected]=> // string(15) "protected_value" // ["private_property":"aClass":private]=> // string(13) "private_value" // ["public_property"]=> // string(12) "public_value" // }
      
      







「リフレクション」を使用すると、たとえば次のようなオブジェクトのすべてのプロパティを取得できます。



 $an_array = array(); $reflection = new ReflectionClass($an_object); $properties = $reflection->getProperties(); foreach ($properties as $property) { $property->setAccessible(true); $an_array[$property->getName()] = $property->getValue($an_object); if (!$property->isPublic()) $property->setAccessible(false); } var_dump($an_array); // array(3) { // ["protected_property"]=> // string(15) "protected_value" // ["private_property"]=> // string(13) "private_value" // ["public_property"]=> // string(12) "public_value" // }
      
      







すべてのプロパティを配列として取得する簡単な方法があります。



 $an_array = (array) $an_object; var_dump($an_array); // array(3) { // [" * protected_property"]=> // string(15) "protected_value" // [" aClass private_property"]=> // string(13) "private_value" // ["public_property"]=> // string(12) "public_value" // }
      
      







必要に応じて、少し「汚い」ことが判明し、不要なデータからキーをクリアできます。 たとえば、次のように:



 $key = ($key{0} === "\0") ? substr($key, strpos($key, "\0", 1) + 1) : $key;
      
      







ところで、配列をオブジェクトに変換する逆のトリックは機能しません。 この方法では、stdClassオブジェクトのみを取得できます。



 $an_another_object = (object) $an_array; var_dump($an_another_object); // object(stdClass)#6 (3) { // ["protected_property":protected]=> // string(15) "protected_value" // ["private_property":"aClass":private]=> // string(13) "private_value" // ["public_property"]=> // string(12) "public_value" // }
      
      







プロパティを取得する方法はまだ文書化されていません。 このメソッドはバグのようにも見えますが、安全ではありません。



 $an_array = array(); reset($an_object); while (list($key, $val) = each($an_object)) $an_array[$key] = $val; var_dump($an_array); // array(3) { // [" * protected_property"]=> // string(15) "protected_value" // [" aClass private_property"]=> // string(13) "private_value" // ["public_property"]=> // string(12) "public_value" // }
      
      







次に、任意のプロパティ(プライベートプロパティを含む)に新しい値を設定するために、 ドキュメント化されていない別のトリックを既に使用できます。



 $an_array["\0aClass\0private_property"] = 'new_private_value'; array_walk($an_object, function(&$val, $key, $array){$val = $array[$key];}, $an_array); var_dump($an_object); // object(aClass)#1 (3) { // ["protected_property":protected]=> // string(15) "protected_value" // ["private_property":"aClass":private]=> // string(17) "new_private_value" // ["public_property"]=> // string(12) "public_value" // }
      
      







おわりに



このケースまたはそのケースを使用すると、この方法でオブジェクトの保護された領域に不正に侵入し、それにより保護またはプライベートとして設定されているすべての保護をバイパスし、オブジェクトはそれについて何も知りません。 したがって、可能であれば、特別なアクセス方法を作成することをお勧めします。



All Articles