เอาสักหน่อยละกันครับ คือผมมีช่วงนึงที่ไม่เข้าใจว่า $test = &test(); หรือ $foo = &$bar; คืออะไร(รู้สึกว่าการเขียนลักษณะนี้จะกลายเป็น trend ไปซะแล้ว) และคิดว่าคงมีอีกหลายคนที่ยังไม่เข้าใจ มาวันนี้ผมจะขออธิบายสั้นๆเพื่อไขข้อสงสัยให้เพื่อนๆได้เข้าใจกันนะครับ
ตาม title เลยครับ จากที่กล่าวมา $test = &test(); หรือ $foo = &$bar;
จะเห็นว่ามี & มันก็คือ Reference ซึ่งจะคล้ายกับตัวแปร Pointer ในภาษาอื่น (เริ่มgetๆ….
) และข้อดีของการใช้ reference ก็คือประหยัดหน่วยความจำ (แต่ใช้เยอะแล้วมึน) เพราะแทนที่ว่าจะ copy ค่าของตัวแปรไปเราก็สามารถใช้ reference แทนได้เลย
ตัวอย่าง
$foo = 1; $bar = &$foo; $bar++; var_dump($foo,$bar);//foo = 2 ,bar = 2 **$foo จะเปลี่ยนตาม $bar //ลอง foo บ้าง $foo++; var_dump($foo,$bar);//foo = 3,bar = 3 **$foo เปลี่ยน $bar ก็เปลี่ยน //unset unset($bar); //จะลบ เฉพาะ $bar , $foo จะไม่ถูก unset ด้วย var_dump($foo,$bar); //foo = 2, bar = NULL
ถ้าเขียนปกติ
$foo = 1; $bar = $foo; $bar++; var_dump($foo,$bar); //foo =1,bar = 2 (ไม่เหมือนกัน)
Return By Reference
ในเวลา เดียวกัน ณ อีกที่แห่งนึงก็มี Pass By Reference -*- ซึ่งมันก็คือ function ที่ return reference กลับมานั่นเอง(อ้อ….Get มั้ยครับถ้า get ไม่เล่าต่อนะ -*-)
และ function นี่จะ return 0;return 1;return ‘test’; ไม่เพราะไม่ได้เป็นตัวแปร ต้อง return $ตัวแปร; เท่านั้นครับ
วิธีการเขียนก็คือ
function &foo()
{
$bar = 1;
return $bar;
}
อะไรประมาณนี้ครับ ในการใช้จริงจาก function ข้างต้นจะเห็นว่า return = 1; ชัวอยู่แล้ว แล้วจะเขียนเป็น return 1; แทนไม่ได้นะครับ เพราะ function นี้เป็น return by reference
*return 1;ได้ครับแต่จะมี error E_NOTICE โผล่มาถ้าหากว่าเปิด error_reporting(E_ALL); หรือ E_NOTICE ไว้ครับ ซึ่ง error ประเภทนี้ดูเหมือนจะจิ๊บๆไม่สำคัญ แต่หากละเลยอาจจะทำให้โปรแกรม/สคริป ของเราไม่ทำงานอย่างที่เราต้องการได้ครับ เพราะตัวแปรที่เป็น NULL หรือ undefined โผล่มาจากไหนไม่ทราบ
* ฉนั้นให้สร้างมาตรฐานของตัวเองขึ้นมาครับว่าต้องเปิด error_reporting(E_ALL); ทุกครั้ง แล้วใช้ if(!empty($var)){} แทน if($var){} ถ้าเกิดว่ามีปัญหาตอน debug เราจะหาจุดที่มีปัญหาเจอได้ง่ายกว่า
เอาหละหลังจากพาไปเกือบออกทะเล ก็กลับมา ณ ที่แห่งนั้น กันต่อครับ
จาก function ข้างต้น &foo จะดู simple มากถ้าหากเอาไปใช้จริงคงเป็นไปไม่ได้ถ้าจะใช้อย่างนั้น
ผมเลยจะขอยกตัวอย่างอีกสักตัวอย่างละกันครับ
Class Foo
{
public $val = 0;
function &getVal()
{
return $this->val;
}
}
$foo = new Foo();
$val = &$foo->getVal();
//ลองเปลี่ยน ค่า $foo->val
$foo->val = 2;
var_dump($val,$foo->val); // ทั้ง $val และ $foo->val มีค่าเท่ากัน
//ลองเปลี่ยนค่า $val ดูบ้าง
$val = 3;
var_dump($val,$foo->val); // $foo->val ก็เป็น 3 เหมือนกับ $val
unset($val);
var_dump($val,$foo->val); // $foo->val จะไมถูก unset และ $val จะ = NULL * บรรทัดนี้จะ error E_NOTICE: undefined $val
มาถึงตรงนี้คงจะมีคำถามแน่ถ้าหากว่า $val = $foo->getVal(); (ไม่ใส่ & นำ)หละ มันก็เท่ากับว่า เรียกใช้ method แบบปกติ แค่ copy ค่าตัวแปรมาเฉยๆครับ
…โอ้ย เริ่มยาวครับ(สันหลัง)…
มาอีกที่นึงจะมี
Pass By Reference
Pass by Reference การใช้งานก็จะคล้ายจะ return by reference ครับ แต่เปลี่ยนจากการ return เป็นการส่งตัวแปรไปแทนครับ
function increase(&$bar)
{
$bar++;
}
$val = 1;
increase($val);
var_dump($val); //2
บ้างครั้ง function ทั่วไปที่เราเขียน แค่ค่า return,การส่งผ่านตัวแปร แบบปกติไม่สามารถทำได้(ดีพอ) การใช้ pass by reference จะเป็นอีกทางเลือกหนึ่งที่ไม่ควรมองข้ามครับ (และก็สามารถ ลดหน่วยความจำได้ด้วย) โดยเฉพาะ Recursive function ที่มีการอ้างถึงตัวแปรอื่น (อย่างเช่น Class Walker ที่ใช้ในการ list comment แบบ nested)
จบครับ By ExpertDuck เอ้ย By &Reference ครับ ฮ่าๆ
ผิดพลาดตรงไหนขออภัยนะครับ ผมเองก็ยังโง่อยู่
ปล. แค่อยากแชร์ครับ ไม่ได้เป็นอาจารย์สอนที่ไหน – -*
สึดยึด