เกริ่นก่อน การ copy object ของ php จริงๆ หลายคนอาจจะนึกถึงอะไรน้อ
$a = $b; หรือว่า clone นั่นแหลครับที่จะมาพูดกัน มาดูแบบแรกกันเลย
1. ใส่เท่ากับกันตรง ๆ (direct equal)
class CopyMe {}
$first = new CopyMe();
$second = $first;
// PHP 4: $second กับ $first จะเป็น 2 object ที่อ้างอิง address คนละอันกันครับซึ่งคือคือคนละ object นั่นเอง
// PHP 5 : $second กับ $first จะถูกมองเป็น object เดียวกันครับ
ซึ่งวิธีนี้อาจจะทำให้เกิดความสับสนกันได้ มาดูวิธีที่ตั้งใจจะมาบอกกันดีกว่าครับ
2. ใช้ฟังก์ชั่น clone (clone function)
วันนี้จะมาเล่นกับ clone นั่นเอง ใครเคยใช้แล้วยกมือขึ้น โย่ว
class CopyMe {}
$first = new CopyMe();
$second = clone $first;
ในเคสนี้ จะได้ $second กับ $first จะเป็นคนละ object กันครับ ฟังก์ชั่น clone จะเป็นการ copy value จาก object นึงไปอีก object นึงครับ ซึ่ง address จะไม่ถูกนำมาด้วย
------------------------------------------------------------------------------------
เทคนิคต่อไป หากเรามีค่าที่ไม่อยากให้ติดมาด้วยหละ เช่น entity ของ database ที่มี $id ที่ไม่อยากให้นำค่ามาด้วย จะทำยังไงดีน้อ เรามีข้อเสนอคือการ overide หรือการเขียนทับ __clone() นั่นเอง มาดูกันเลย
class Person {
private $name;
private $age;
private $id;
function __construct( $name, $age ) {
$this->name = $name;
$this->age = $age;
}
function setId( $id ) {
$this->id = $id;
}
function __clone() {
$this->id = 0; // ทำการกำหนดค่า id ให้เป็น 0 เมื่อเกิดการ clone ครับ
}
}
$person = new Person( "me", 27 );
$person->setId( 343 );
$person2 = clone $person;
// $person2 :
// name: me
// age: 27
// id: 0
ง่ายมั้ยครับ
------------------------------------------------------------------------------------
เอา next step ต่อไปมาดูว่าถ้าใน object ของเรา reference ของ object อื่นด้วยหละ
class Account {
public $balance;
function __construct( $balance ) {
$this->balance = $balance;
}
}
class Person {
private $name;
private $age;
private $id;
public $account; // ตัวนี้เป็น Object ของ Account ครับ ซึ่งเมื่อถูก clone จะได้ reference ไป
function __construct( $name, $age, Account $account ) {
$this->name = $name;
$this->age = $age;
$this->account = $account;
}
function setId( $id ) {
$this->id = $id;
}
function __clone() {
$this->id = 0;
}
}
$person = new Person( "bob", 44, new Account( 200 ) );
$person->setId( 343 );
//เรามาเพิ่มเงินให้หน่อยดีกว่า คราวนี้คนแรกมีเงิน 210 บาทแล้ว
$person->account->balance += 10;
//เอ๊ะ ทำไมคนที่สองก็มีเงิน 210 บาทเหมือนกันเพราะเป็นการ copy reference มานั่นเอง
print $person2->account->balance;
------------------------------------------------------------------------------------
แก้โดย
function __clone() {
$this->id = 0;
$this->account = clone $this->account;
}
ใส่ clone ซ้ำใน __clone() ซะเลย แค่นี้ก็เรียบร้อยแล้ว
หวังว่าจะทำให้เกิดไอเดียใช้สนุก ๆ นะครับ
ความรู้จาก PHP Obejcts, Pattern and Practice (3rd)