对这个动态类我想做的最后一个改进,是用成员变量访问字段,而不是用笨重的 get_ 和 set_ 操作符。清单 7 显示了如何用 __get 和 __set 魔法方法代替 __call。
清单 7. 使用 __get 和 __set 方法- <?php
- require_once("DB.php");
- $dsn = 'mysql://root:password@localhost/bookdb';
- $db =& DB::Connect( $dsn, array() );
- if (PEAR::isError($db)) { die($db->getMessage()); }
- class DBObject
- {
- private $id = 0;
- private $table;
- private $fields = array();
- function __construct( $table, $fields )
- {
- $this->table = $table;
- foreach( $fields as $key )
- $this->fields[ $key ] = null;
- }
- function __get( $key )
- {
- return $this->fields[ $key ];
- }
- function __set( $key, $value )
- {
- if ( array_key_exists( $key, $this->fields ) )
- {
- $this->fields[ $key ] = $value;
- return true;
- }
- return false;
- }
- function load( $id )
- {
- global $db;
- $res = $db->query(
- "SELECT * FROM ".$this->table." WHERE ".
- $this->table."_id=?",
- array( $id )
- );
- $res->fetchInto( $row, DB_FETCHMODE_ASSOC );
- $this->id = $id;
- foreach( array_keys( $row ) as $key )
- $this->fields[ $key ] = $row[ $key ];
- }
- function insert()
- {
- global $db;
- $fields = $this->table."_id, ";
- $fields .= join( ", ", array_keys( $this->fields ) );
- $inspoints = array( "0" );
- foreach( array_keys( $this->fields ) as $field )
- $inspoints []= "?";
- $inspt = join( ", ", $inspoints );
- $sql = "INSERT INTO ".$this->table.
- " ( $fields ) VALUES ( $inspt )";
- $values = array();
- foreach( array_keys( $this->fields ) as $field )
- $values []= $this->fields[ $field ];
- $sth = $db->prepare( $sql );
- $db->execute( $sth, $values );
- $res = $db->query( "SELECT last_insert_id()" );
- $res->fetchInto( $row );
- $this->id = $row[0];
- return $row[0];
- }
- function update()
- {
- global $db;
- $sets = array();
- $values = array();
- foreach( array_keys( $this->fields ) as $field )
- {
- $sets []= $field.'=?';
- $values []= $this->fields[ $field ];
- }
- $set = join( ", ", $sets );
- $values []= $this->id;
- $sql = 'UPDATE '.$this->table.' SET '.$set.
- ' WHERE '.$this->table.'_id=?';
- $sth = $db->prepare( $sql );
- $db->execute( $sth, $values );
- }
- function delete()
- {
- global $db;
- $sth = $db->prepare(
- 'DELETE FROM '.$this->table.' WHERE '.
- $this->table.'_id=?'
- );
- $db->execute( $sth,
- array( $this->id ) );
- }
- function delete_all()
- {
- global $db;
- $sth = $db->prepare( 'DELETE FROM '.$this->table );
- $db->execute( $sth );
- }
- }
- class Book extends DBObject
- {
- function __construct()
- {
- parent::__construct( 'book',
- array( 'author', 'title', 'publisher' ) );
- }
- }
- $book = new Book( );
- $book->delete_all();
- $book->{'title'} = "PHP Hacks";
- $book->{'author'} = "Jack Herrington";
- $book->{'publisher'} = "O'Reilly";
- $id = $book->insert();
- echo ( "New book id = $id\n" );
- $book->{'title'} = "Podcasting Hacks";
- $book->update();
- $book2 = new Book( );
- $book2->load( $id );
- echo( "Title = ".$book2->{'title'}."\n" );
- $book2->delete( );
- ?>
-
复制代码 底部的测试代码只演示了这个语法干净了多少。要得到图书的书名,只需得到 title 成员变量。这个变量会调用对象的 __get 方法,在散列表中查找 title 条目并返回。
现在就得到了单个动态的数据库访问类,它能够让自己适应到数据库中的任何表。 |