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의 객체에는 참조 유형의 속성이 포함될 수 있습니다. Clone을 사용하는 경우 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");
// 사용 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 객체의 친구 배열은 완전히 독립적입니다. 우리가 클론 에서 친구 배열을 수정하더라도 원래 객체의 친구 배열은 영향을받지 않습니다. 이는 직렬화 및 비 제외 화가 객체의 깊은 사본을 생성하고 참조 유형의 모든 속성이 독립적으로 복사되기 때문입니다.
직렬화 함수는 전체 객체를 문자열로 변환하고 참조 유형의 모든 속성을 포함하여 객체의 모든 속성을 처리합니다. 비 시절을 통해 객체를 복원 할 때 PHP는 새 개체 인스턴스를 생성하고 모든 속성을 복사하여 독립적인지 확인합니다. 따라서 배열 또는 기타 객체와 같은 참조 유형의 모든 속성은 원본 및 복제 된 객체간에 공유되지 않습니다.
이 접근법의 장점 중 하나는 객체의 __clone 방법 또는 __sleep 및 __wakeup 방법에 의존하지 않고 직렬화 및 사막화를 통해 딥 카피를 직접 구현한다는 것입니다.
직렬화 및 비 제외 화는 효과적인 솔루션을 제공하지만 몇 가지 제한 사항도 있습니다.
성능 문제 : 대형 대상의 경우, 특히 객체에 속성이 많은 경우 직렬화 및 사막화 과정이 느려질 수 있습니다.
직렬화되지 않은 객체 : 일부 개체 (예 : 직렬화 할 수없는 리소스 유형 또는 클래스)는 직렬화 로 직렬화되지 않아 오류가 발생할 수 있습니다.
따라서 깊은 복사를 위해 직렬화를 사용할 때는 실제 조건에 따라 장점과 단점을 측정해야합니다.
직렬 화 및 비 제외 기능을 사용하면 객체를 복제 할 때 공유 참조 문제를 피할 수 있습니다. 이 방법은 복제 된 객체와 원래 객체의 속성이 객체의 깊은 사본을 만들어 서로 영향을 미치지 않도록합니다. 특히 객체에 배열 또는 기타 참조 유형의 속성이 포함 된 경우.
실제 발전에서, 일련 화 및 비 제외 사용을 사용하는 것은 복잡한 물체를 다루고 복제하는 동안 오류를 피해야한다면 매우 효과적인 솔루션입니다.
기사에 API 호출 등과 같은 URL 부품이 포함 된 경우 다음과 같이 도메인 이름을 gitbox.net 으로 바꿀 수 있습니다.
$url = "https://gitbox.net/api/getData";
이런 식으로 네트워크 요청에서도 URL이 지정한 도메인 이름 gitbox.net 을 올바르게 가리 키게 할 수 있습니다.