PHP项目对象如何克隆复制

wen PHP项目 24

本文目录导读:

PHP项目对象如何克隆复制

  1. 使用 clone 关键字(浅拷贝)
  2. 实现 __clone() 方法(深拷贝)
  3. 使用序列化实现深拷贝
  4. 使用工厂方法模式
  5. 完整示例:处理各种复杂情况
  6. 注意事项

在PHP中,克隆(复制)对象主要有以下几种方式:

使用 clone 关键字(浅拷贝)

class User {
    public $name;
    public $profile;
    public function __construct($name, $profile) {
        $this->name = $name;
        $this->profile = $profile;
    }
}
$user1 = new User('张三', ['age' => 25, 'city' => '北京']);
$user2 = clone $user1;
// 修改克隆对象
$user2->name = '李四';
$user2->profile['age'] = 30;
echo $user1->name; // 张三(不受影响)
echo $user1->profile['age']; // 30(受影响!因为对象引用被共享)

实现 __clone() 方法(深拷贝)

class User {
    public $name;
    public $profile;
    public $address; // 对象类型属性
    public function __construct($name, $profile, Address $address) {
        $this->name = $name;
        $this->profile = $profile;
        $this->address = $address;
    }
    public function __clone() {
        // 深拷贝对象类型属性
        if ($this->address instanceof Address) {
            $this->address = clone $this->address;
        }
        // 深拷贝数组(可选)
        if (is_array($this->profile)) {
            // 数组本身就是值拷贝,但如果是关联数组或嵌套数组
            $this->profile = $this->deepCopyArray($this->profile);
        }
    }
    private function deepCopyArray($array) {
        $result = [];
        foreach ($array as $key => $value) {
            if (is_object($value)) {
                $result[$key] = clone $value;
            } elseif (is_array($value)) {
                $result[$key] = $this->deepCopyArray($value);
            } else {
                $result[$key] = $value;
            }
        }
        return $result;
    }
}
class Address {
    public $city;
    public $street;
    public function __construct($city, $street) {
        $this->city = $city;
        $this->street = $street;
    }
}
// 使用
$address = new Address('北京', '长安街');
$user1 = new User('张三', ['age' => 25, 'city' => '北京'], $address);
$user2 = clone $user1;
$user2->address->city = '上海';
echo $user1->address->city; // 北京(不受影响,深拷贝成功)

使用序列化实现深拷贝

function deepClone($object) {
    return unserialize(serialize($object));
}
// 或者使用 PHP 8.0+ 的 __serialize() 和 __unserialize()
class User implements Serializable {
    public $name;
    private $data;
    public function serialize() {
        return serialize([
            'name' => $this->name,
            'data' => $this->data
        ]);
    }
    public function unserialize($data) {
        $arr = unserialize($data);
        $this->name = $arr['name'];
        $this->data = $arr['data'];
    }
}

使用工厂方法模式

class User {
    public $name;
    public $email;
    public static function from(User $user): self {
        $clone = new self();
        $clone->name = $user->name;
        $clone->email = $user->email;
        return $clone;
    }
}
// 使用
$user1 = new User();
$user1->name = '张三';
$user2 = User::from($user1);

完整示例:处理各种复杂情况

class SerializableObject {
    private $resources = [];
    public function __clone() {
        // 清理资源
        foreach ($this->resources as &$resource) {
            // 重新分配资源
        }
        // 复制其他属性
        foreach (get_object_vars($this) as $property => $value) {
            if (is_object($value)) {
                $this->$property = clone $value;
            }
        }
    }
}

注意事项

  1. 浅拷贝 vs 深拷贝

    • clone 默认是浅拷贝,只复制对象本身
    • 需要手动处理对象类型属性的克隆
  2. 不可克隆对象

    class Singleton {
        private function __clone() {
            throw new \Exception('Cannot clone singleton');
        }
    }
  3. 循环引用处理

    class Node {
        public $next;
        public $value;
        public function __clone() {
            if ($this->next !== null) {
                $this->next = clone $this->next;
            }
        }
    }

选择哪种方式取决于你的具体需求:

  • 简单对象:直接用 clone
  • 复杂对象:实现 __clone() 方法
  • 需要完全独立:使用序列化/反序列化
  • 定制化克隆:使用工厂方法

抱歉,评论功能暂时关闭!