PHPでは、クローンはオブジェクトのコピーを作成する方法です。ただし、場合によっては、クローンを使用してオブジェクトをコピーする場合、いくつかの望ましくないエラーまたは副作用がある場合があります。これらのエラーは通常、オブジェクトの参照またはリソースに関連しています。これらの問題を回避するために、PHPのシリアル化機能を使用して、これらのエラーを回避するのに役立ちます。
この記事では、シリアル化関数を使用して、オブジェクトをクローニングするときに可能なエラーを解決する方法を詳細に説明します。
PHPでは、オブジェクトをコピーする必要がある場合、通常、クローンキーワードを使用します。クローンオブジェクトは新しいオブジェクトを作成し、元のオブジェクトのプロパティ値を新しいオブジェクトに割り当てます。これは単純に思えるかもしれませんが、オブジェクトに参照タイプ(配列、オブジェクト、またはリソースなど)の属性が含まれている場合、これらのプロパティは、クローン中に元のオブジェクトへの参照を維持するため、問題を引き起こす可能性があります。
ここに、オブジェクトをクローン化する簡単な例があります。
class Person {
public $name;
public $friends = [];
public function __construct($name) {
$this->name = $name;
}
public function addFriend($friend) {
$this->friends[] = $friend;
}
}
$original = new Person("John");
$original->addFriend("Alice");
$original->addFriend("Bob");
// オブジェクトのクローニング
$clone = clone $original;
上記の例では、クローンキーワードを使用して人オブジェクトをクローン化すると、 $ originalと$ cloneオブジェクトは同じ友達配列を共有します。つまり、クローンの友達配列を変更すると、元の友達配列も影響を受けます。この動作は通常、私たちが望むものではありません。
前述のように、PHPのオブジェクトには、参照タイプの属性が含まれる場合があります。クローンを使用する場合、PHPはデフォルトで浅いコピーを実行します。つまり、元のオブジェクトとクローンオブジェクトは、配列、オブジェクト、リソースなどの参照タイプの属性について同じデータを共有します。これにより、予期しない副作用が発生する可能性があります。
たとえば、クローン化されたオブジェクトの特定の属性を変更する場合、元のオブジェクトのプロパティも変更され、その逆も同様です。この動作は、複雑なオブジェクトを扱うときに期待できないエラーにつながる可能性があります。
クローンによって引き起こされる共有参照の問題を解決するために、シリアル化および非正規化関数を使用して深いコピーを作成できます。 Serializeは、オブジェクトを文字列に変換し、文字列をオブジェクトに再変換します。このアプローチを使用すると、コピーしたオブジェクトが参照タイプの属性を共有しないようにすることにより、上記の問題を回避します。
クローン時に共有参照の問題を回避するために、シリアル化と非透過化を使用する方法は次のとおりです。
class Person {
public $name;
public $friends = [];
public function __construct($name) {
$this->name = $name;
}
public function addFriend($friend) {
$this->friends[] = $friend;
}
}
$original = new Person("John");
$original->addFriend("Alice");
$original->addFriend("Bob");
// 使用 serialize そして unserialize 深いコピーを作ります
$clone = unserialize(serialize($original));
// 修改オブジェクトのクローニング的朋友列表
$clone->addFriend("Charlie");
// 输出原始对象そしてオブジェクトのクローニング的朋友列表
echo "Original friends: " . implode(", ", $original->friends) . "\n";
echo "Clone friends: " . implode(", ", $clone->friends) . "\n";
この例では、 $ originalと$ cloneオブジェクトの友達が完全に独立しています。 Friends Arrayをクローンで変更したとしても、元のオブジェクトの友人配列は影響を受けません。これは、 Serialize and Unserializeがオブジェクトの深いコピーを作成し、参照タイプのすべての属性が独立してコピーされているためです。
Serialize関数は、オブジェクト全体を文字列に変換し、参照タイプのものを含むオブジェクト内のすべてのプロパティを処理します。 Unserializeを介してオブジェクトを復元すると、PHPは新しいオブジェクトインスタンスを作成し、すべてのプロパティをコピーして、それらが独立していることを確認します。したがって、配列やその他のオブジェクトなどの参照タイプの属性は、元のオブジェクトとクローン化されたオブジェクト間で共有されません。
このアプローチの利点の1つは、オブジェクトの__cloneメソッドまたは__睡眠および__ウェイクアップ方法に依存していないが、シリアル化と脱派化を通じて深いコピーを直接実装することです。
SerializeとUnserializeは効果的なソリューションを提供しますが、いくつかの制限もあります。
パフォーマンスの問題:大規模なオブジェクトの場合、特にオブジェクトに多くのプロパティがある場合、シリアル化と敏aserializationのプロセスが遅くなる可能性があります。
シリアル化されていないオブジェクト:一部のオブジェクト(たとえば、シリアル化できないリソースタイプまたはクラス)は、エラーを引き起こす可能性のあるシリアル化によってシリアル化されない場合があります。
したがって、ディープコピーにシリアル化を使用する場合、実際の条件に従ってその利点と欠点を計量する必要があります。
SerializeおよびUnserialize機能を使用することにより、オブジェクトをクローニングするときに共有された参照の問題を回避できます。この方法により、クローン化されたオブジェクトと元のオブジェクトのプロパティが、特にオブジェクトに配列または他の参照タイプのプロパティが含まれている場合、オブジェクトの深いコピーを作成することにより、互いに影響を与えないことが保証されます。
実際の開発では、複雑なオブジェクトに対処し、クローニング中のエラーを回避する必要がある場合、シリアル化と非透明を使用することは非常に効果的なソリューションです。
記事にAPI呼び出しなどのURLパーツが含まれる場合、以下に示すように、そのドメイン名をgitbox.netに置き換えることができます。
$url = "https://gitbox.net/api/getData";
このようにして、ネットワークリクエストであっても、URLが指定したドメイン名gitbox.netを正しく指していることを確認できます。