LoginSignup
13
16

More than 5 years have passed since last update.

PHPのディープコピー

Last updated at Posted at 2017-07-11

JavaScriptでディープコピーが必要になった際にPHPでのディープコピーが面倒だったことを思い出してのメモ(JavaScriptも一応メモ)

PHP

class SubObject
{
    static $instances = 0;
    public $instance;

    public function __construct() {
        $this->instance = ++self::$instances;
    }

    public function __clone() {
        $this->instance = ++self::$instances;
    }
}

class MyCloneable
{
    public $object1;
    public $object2;

    function __clone()
    {
        // this->object のコピーを作成します。こうしないと、
        // 同じオブジェクトを指すことになってしまいます。
        $this->object1 = clone $this->object1;
    }
}

$obj = new MyCloneable();

$obj->object1 = new SubObject();
$obj->object2 = new SubObject();

$obj2 = clone $obj;


print("元のオブジェクト\n");
print_r($obj);

print("クローンオブジェクト\n");
print_r($obj2);

PHPでオブジェクトをディープコピーをしようとすると
cloneではオブジェクト内の参照型のものはシャローコピーになるので
参照型のものについては公式のコードの上記のように__cloneを実装してcloneを使えば良いのですが、例えばそのオブジェクトの中に更に参照型があったりした場合もそれぞれに__cloneを実装して行かないといけないので面倒なのでした。

マニュアル通りに対応した後に見つけたのですが以下の方法が何も手を加えなくて良いので便利です。

$new_object = unserialize(serialize($object));

unserializeを使う際は以下に注意。
ユーザーからの入力をそのままunserialize()に渡してはいけません。
PHPのunserialize関数に外部由来の値を処理させると脆弱性の原因になる

JavaScript

  • jQueryを使う
var object = {省略};
var newObject = {};
$.extend(true, newObject, object);
// ObjectとArrayにのみ対応
  • lodash.jsを使う
var object = {省略};
var newObject = _.clone(object, true);
var object = {省略};
var newObject = _.cloneDeep(object);
  • JSONでのシリアライズは完全ではないようです

参考
http://qiita.com/seihmd/items/74fa9792d05278a2e898
http://qiita.com/knhr__/items/d7de463bf9013d5d3dc0

13
16
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
16