*บันทึกไว้อ่านกันลืม
พอดีวันนี้ได้กลับมาเขียน PHP แบบที่ต้องเชื่อมต่อกับฐานข้อมูลเองผ่าน mysql_* ที่ติดมากับ PHP หลังจากไม่ได้ใช้มานานแล้วตั้งแต่สมัยมหาวิทยาลัย แต่หลังจากใช้ไปได้สักพักก็เกิดความรู้สึกที่ว่าการใช้ mysql_fetch_array
เหมือนที่เคยใช้มันไม่ค่อยสวยเท่าไหร่ พอดีเหลือบไปเห็น mysql_fetch_object
เมื่อก่อนก็เคยใช้ แต่พี่งสังเกตว่าเราสามารถระบุคลาสมารับข้อมูลที่อ่านมาได้ เหมือนกับ Object Model ในพวก ORM วันนี้ก็เลยลองของสักหน่อย
ได้โค้ดทั้งหมดดังนี้
<?php $connection = null; function __db_connection() { global $connection; $connection = mysql_pconnect( '127.0.0.1', 'foo', 'bar' ); if ( ! $connection ) $connection = mysql_pconnect( '127.0.0.1', 'foo', 'bar' ); mysql_select_db( 'my_db_name' ); mysql_query( 'set names utf8' ); }; class SL_Foo { protected $_foo = array( 'ID' => '', 'message' => '', 'timestamp' => '' ); function __get( $name ) { global $datetime_format; if ( in_array( $name, array( 'timestamp' ) ) ) return date( $datetime_format, strtotime( $this->_foo[ $name ] ) ) ; return @$this->_foo[ $name ]; } function __set( $name, $value ) { $this->_foo[ $name ] = $value ; } } if ( ! $connection ) __db_connection(); $sql = sprintf( "select * from foo where ID = '%s'", addslashes( $_REQUEST['id'] ) ); $results = mysql_query( $sql, $connection ) ; if ( ! $results ) printf( 'MySQL Error: %s', mysql_error() ) ; $foos = array(); if ( mysql_num_rows( $results ) ) while( $foo = mysql_fetch_object( $results, 'SL_Foo' ) ) $foos[] = $foo; mysql_free_results( $results ); // Do something with $foos echo var_dump( $foos );
อธิบายโค้ดได้ดังนี้ครับ
- บรรทัดที่ 2: สร้างตัวแปรเพื่อเก็บการเชื่อมต่อกับฐานข้อมูล
- บรรทัดที่ 4-13: ฟังก์ชั่นสำหรับการเชื่อมต่อกับฐานข้อมูล
- บรรทัดที่ 15-34: คือคลาสที่สร้างขึ้นเพื่อรับข้อมูลที่อ่านได้จากฐานข้อมูล โดยมีชื่อฟิลด์คือ
ID
,message
,timestamp
ซึ่งชื่อนี้ต้องเหมือนกันกับชื่อฟิลด์ที่มีในฐานข้อมูลแบบ case sensitive - บรรทัดที่ 22-32: เป็น Magic methods ของ PHP โดยที่
__get
คือเมธอดที่ใช้อ่านค่าต่างๆ ของคลาส โดยสามารถกำหนดเงื่อนไขการการแสดงผลของค่าที่คืนไปได้ เช่นในตัวอย่างคือถ้าค่าที่ผู้ใช้ต้องการคือtimestamp
ให้เปลี่ยนรูปแบบจากรูปแบบมาตรฐานในฐานข้อมูลให้กลายเป็นรูปแบบตามที่กำหนดในตัวแปร$datetime_format
- บรรทัดที่ 36: สร้างการเชื่อมต่อ
- บรรทัดที่ 38-41: สร้าง Query String และส่งข้อมูล Query เข้าสู่ฐานข้อมูล
- บรรทัดที่ 45: อ่านค่าที่ได้จาก
$results
ออกมาเป็น Object โดยนำคลาสSL_Foo
ที่กำหนดไว้ข้างต้นมารับค่าที่อ่านได้
จะเห็นได้ว่า ข้อดีของการสร้างคลาสเข้ามารองรับการทำงานแบบนี้คือเราสามารถกำหนดรูปแบบการแสดงผลของข้อมูลที่เราต้องการได้ อย่างเช่นเปลี่ยนแปลงรูปแบบวันที่ตามที่เราต้องการในตัวอย่าง นอกจากนั้นยังทำให้ดูแลจัดการโครงสร้างข้อมูลได้ง่ายขึ้น
* แก้ไข
เนื่องจากดูโค้ดแล้วมันดูเยิ้นเย้อในส่วนของฐานข้อมูลซึ่งสามารถลดลงได้ดังนี้
<?php $connection = null; function __db_connection() { global $connection; $connection = mysql_pconnect( '127.0.0.1', 'foo', 'bar' ); if ( ! mysql_ping( $connection ) ) { $connection = mysql_pconnect( '127.0.0.1', 'foo', 'bar' ); } mysql_select_db( 'my_db_name' ); mysql_query( 'set names utf8' ); }; class SL_Foo { protected $_foo = array(); function __get( $name ) { global $datetime_format; if ( in_array( $name, array( 'timestamp' ) ) ) return date( $datetime_format, strtotime( $this->_foo[ $name ] ) ) ; return @$this->_foo[ $name ]; } function __set( $name, $value ) { $this->_foo[ $name ] = $value ; } } if ( ! $connection ) __db_connection(); $sql = sprintf( "select * from foo where ID = '%s'", addslashes( $_REQUEST['id'] ) ); $results = mysql_query( $sql, $connection ) ; if ( ! $results ) printf( 'MySQL Error: %s', mysql_error() ) ; $foos = array(); if ( mysql_num_rows( $results ) ) while( $foo = mysql_fetch_object( $results, 'SL_Foo' ) ) $foos[] = $foo; mysql_free_results( $results ); // Do something with $foos echo var_dump( $foos );
- บรรทัดที่ 8-12 รวมเป็นบรรทัดเดียวกัน เพื่อลดการเชื่อมต่อกับฐานข้อมูลตอนสั่งเปิดการเชื่อมต่อ
- คลาส
SL_Foo
ลบการใส่คีย์เป็นค่าเริ่มต้น เนื่องจากคลาสใช้ Magic Methods และด้วยวิธีการเขียนทำให้จะระบุหรือไม่ก็ไม่ส่งผลกระทบกับการทำงาน