ภาพประกอบ : zend transaction

Zend Framework วิธีบันทึกข้อมูลร่วมกับ Transaction

Zend Framework ต่อกันนะครับ เมื่อบทความที่แล้วพูดไปถึงเรื่องของการบันทึกข้อมูลลงไปในฐานข้อมูลแบบพื้นฐานกันไปแล้วนะครับ วันนี้ผมจะมาพูดต่อเรื่องเดิมแต่เพิ่มความสามารถของระบบเข้าไปอีกนิดด้วย Transaction มาลองทำความรู้จักดูว่า Transaction คืออะไรและใช้ในการ ติดต่อกับฐานข้อมูลได้อย่างไร

ภาพประกอบ : zend transaction

ภาพประกอบ : zend transaction

Zend Framework Transaction คืออะไร

เริ่มจากมาทำความรู้จักกับ transaction กันก่อนนะครับว่าคืออะไร แล้วมีไว้เพื่ออะไร transaction หมายถึงการกระทำงานใดๆซักอย่างร่วมกับฐานข้อมูลครับ ให้นึกถึงภาพประมาณว่า คุณใช้งานเครื่อง ATM แล้วคุณทำการใส่บัตรเข้าไป เลือกรายการ ระบุรายละเอียด รอจนรายการสำเร็จ ได้รับบัตรคืน แบบนีเรียกว่า 1 transaction ครับ

ทีนี้การทำงานกับฐานข้อมูลก็คล้ายๆกันคือเราจะใช้งาน transaction เพื่อให้มันช่วยเราตรจสอบว่าระหว่างทางในการทำ 1 transaction นั้นมีปัญหาไหม  ถ้ามีก็อย่าเพิ่งทำงานต่อไป อย่าเพิ่งบันทึกข้อมูลลงไปในฐานข้อมูล อย่าเพิ่งอัพเดทข้อมูลใดๆ ต้องรอให้ทุกอย่างชัวร์เสียก่อน

ทีนี้ฐานข้อมูลทุกตัวจะสามารถใช้งาน transaction ได้รึเปล่า อันนี้ต้องดูรายละเอียดเพิ่มเติมกันด้วยนะครับแต่โดยส่วนใหญ่แล้วก็ใช้งานได้กันทั้งนั้น และที่เราใช้ในการเขียนเรื่องนี้ก็คือ MySQL ก็รองรับด้วยนะครับ งั้นเรามาเริ่มกันเลยดีกว่า

ข้อมูลของ transaction ที่เราจะใช้ในการ Save ข้อมูลลงฐานข้อมูลนั้นคุณจะต้องรู้จักกับ 2 คำนี้ครับ

1.commit เป็นการสั่งให้ข้อมูลทุกอย่างใน transaction นั้นๆสามารถจบการทำงานได้ อันนี้เราจะใช้เป็นเงื่อนไขหากมีการทำงานที่ผ่านไปได้ด้วยดีครับ
2.rollback เป็นการสั่งให้ข้อมูลใน transaction นั้นย้อนกลับไปไม่ต้องทำการบันทึกใดๆครับ เราจะใช้เป็นเงื่อนไขหาก save ไม่ผ่านนั้นเอง

เอาละครับให้อิงจาก Code เดิมที่เป็นบทความเมื่อตอนที่แล้วไว้ด้วยนะครับ คือผมจะใช้ function ที่ชื่อว่า  addcustomer ใน index controller เหมือนเดิม ใช้ $aFormData ในการจัดเก็บข้อมูลเพื่อทำการ save และจะเรียกผ่านทาง model ที่ชื่อว่า customer tbl เหมือนเดิมนะครับ

public function addcustomerAction()
 {
 // initial table
 $oCustomerTbl = new Application_Model_DbTable_CustomerTbl();
 // set data to save
 $aFormData = array();
 $aFormData['first_name'] = "porar";
 $aFormData['last_name'] = "merk";
 $aFormData['email'] = "[email protected]";
 $aFormData['country'] = "poland";
 $aFormData['ip_address'] = "192.168.1.1";
 // call function save
 $addCustomer = $oCustomerTbl->save($aFormData);
 // Debug Code
 Zend_debug::dump($aFormData);
 }

ผมทำการระบุข้อมูลที่ต้องการ save ไว้ใน $sFormData เรียบร้อยแล้วนะครับ และทำการเรียก model แล้ว และเรียก function save พร้อมทั้งส่งข้อมูลเข้าไปใน function ด้วย และบรรทัดสุดม้ายผม dump ค่าไว้โชว์ตอน save นะครับ

ทีนี้ความแตกต่างจากบทที่แล้วจะอยู่ที่ส่วนของ Model ครับ Model ที่ชื่อ save จะถูกเปลี่ยนไป โดยเริ่มต้นนั้นคุณจะ้องทำการเรียก Default Adapter ของ Zend ขึ้นมาใช้งานก่อน

$oDb = Zend_Db_Table_Abstract::getDefaultAdapter();

จากนั้นก็ให้ทำการเปิด transaction ด้วยคำสั่ง beginTransaction

$oDb->beginTransaction();

แล้วก็เรียกฐานข้อมูลขึ้นมาเตรียมใช้งานในตัว model นั้นแหละ

$oCustomerTbl = new Application_Model_DbTable_CustomerTbl();

ทีนี้เราจะเรียกส่วนของ try catch ขึ้นมาเพื่อครอบพื้นที่การทำงานครับ เริ่มจาก try คือส่วนที่ผมอยากให้เค้า “ลอง” ทำธุรกรรมดู หากว่าทำสำเร็จก็ให้ commit ไปได้เลยในกรอบของ try แต่หากว่าไม่สำเร็จให้ไปทำในส่วนของกรอบ catch ซึ่งนั้นก็คือการสั่ง rollback นั้นเองครับ

try{
"ทำธุรกรรม"
"ถ้าสำเร็จให้ commit"
}catch{
"ถ้า Try ไม่ผ่านให้ rollback"
}

concept จะออกมาประมาณนี้นะครับ พอเขียนจริงๆก็จะเป็นแบบนี้


try {
// create row and insert new data
$oCustomerRow = $oCustomerTbl->createRow();
$oCustomerRow->setFromArray($data);
$iCustomerId = $oCustomerRow->save();

// if all successful commit to DB
if (null !== $iCustomerId){
// commit database
$oDb->commit();
}

} catch () {
$oDb->rollBack();
return;
}

ในตัวอย่างผมทำการสร้างแถวขึ้นมาก่อน 1 แถวด้วยคำสั่ง createRow() และจับเอาข้อมูลที่ส่งมายัดใส่ไว้และทำการ save ถ้างานนี้ผ่านก็จะได้ค่ามี 1 ค่าเก็บเป็น id ไว้ แล้วพอจะเช็คจริงๆก็เอาค่า id มาตรวจสอบด้วย null ดูว่ามีค่าอยู่ไหม ถ้ามีก็ commit ไปได้เลย แต่ถ้าไม่มีก็ให้ไปทำงานในส่วนของ catch ไม่ต้อง commit ในส่วนของ rollback ก็คือการคืนค่าต่าๆกลับมาไม่ต้องทำการ save นั้นเอง


public function save($data)
{
// use transaction
$oDb = Zend_Db_Table_Abstract::getDefaultAdapter();
$oDb->beginTransaction();

// initial table
$oCustomerTbl = new Application_Model_DbTable_CustomerTbl();

try {
// create row and insert new data
$oCustomerRow = $oCustomerTbl->createRow();
$oCustomerRow->setFromArray($data);
$iCustomerId = $oCustomerRow->save();

// if all successful commit to DB
if (null !== $iCustomerId){
// commit database
$oDb->commit();
}

} catch () {
$oDb->rollBack();
return;
}
}

ภาพประกอบ :: save

ภาพประกอบ :: save

ซึ่งถ้าข้อมูลเราไม่มีปัญหาอะไรก็จะผ่านไปได้ครับ เพียงเท่านี้เองสำหรับใช้ transaction เข้ามาช่วยในการทำงานกับฐานข้อมูล นอกจากจะทำกับการ insert แล้วเรายังทำงานในส่วนอื่นๆได้อีกนะครับทั้ง create update deleted นั้นแหละครับ เอาเป็นว่าใช้พื้นฐานกันเป็นแล้วก็ลองนำไปประยุกต์ใช้งานในรูปแบบต่างๆกันดูนะครับ

อ้างอิง http://framework.zend.com/manual/1.12/en/zend.db.table.html