返回列表 发帖

用 PHP 走向动态6 --改进的空间

对这个动态类我想做的最后一个改进,是用成员变量访问字段,而不是用笨重的 get_ 和 set_ 操作符。清单 7 显示了如何用 __get 和 __set 魔法方法代替 __call。


清单 7. 使用 __get 和 __set 方法
  1. <?php
  2. require_once("DB.php");
  3. $dsn = 'mysql://root:password@localhost/bookdb';
  4. $db =& DB::Connect( $dsn, array() );
  5. if (PEAR::isError($db)) { die($db->getMessage()); }
  6. class DBObject
  7. {
  8.   private $id = 0;
  9.   private $table;
  10.   private $fields = array();
  11.   function __construct( $table, $fields )
  12.   {
  13.     $this->table = $table;
  14.     foreach( $fields as $key )
  15.       $this->fields[ $key ] = null;
  16.   }
  17.   function __get( $key )
  18.   {
  19.     return $this->fields[ $key ];
  20.   }
  21.   function __set( $key, $value )
  22.   {
  23.     if ( array_key_exists( $key, $this->fields ) )
  24.     {
  25.       $this->fields[ $key ] = $value;
  26.       return true;
  27.     }
  28.     return false;
  29.   }
  30.   function load( $id )
  31.   {
  32.     global $db;
  33.     $res = $db->query(
  34.   "SELECT * FROM ".$this->table." WHERE ".
  35.    $this->table."_id=?",
  36.       array( $id )
  37.     );
  38.     $res->fetchInto( $row, DB_FETCHMODE_ASSOC );
  39.     $this->id = $id;
  40.     foreach( array_keys( $row ) as $key )
  41.       $this->fields[ $key ] = $row[ $key ];
  42.   }
  43.   function insert()
  44.   {
  45.     global $db;
  46.     $fields = $this->table."_id, ";
  47.     $fields .= join( ", ", array_keys( $this->fields ) );
  48.     $inspoints = array( "0" );
  49.     foreach( array_keys( $this->fields ) as $field )
  50.       $inspoints []= "?";
  51.     $inspt = join( ", ", $inspoints );
  52. $sql = "INSERT INTO ".$this->table.
  53.    " ( $fields ) VALUES ( $inspt )";
  54.     $values = array();
  55.     foreach( array_keys( $this->fields ) as $field )
  56.       $values []= $this->fields[ $field ];
  57.     $sth = $db->prepare( $sql );
  58.     $db->execute( $sth, $values );
  59.     $res = $db->query( "SELECT last_insert_id()" );
  60.     $res->fetchInto( $row );
  61.     $this->id = $row[0];
  62.     return $row[0];
  63.   }
  64.   function update()
  65.   {
  66.     global $db;
  67.     $sets = array();
  68.     $values = array();
  69.     foreach( array_keys( $this->fields ) as $field )
  70.     {
  71.       $sets []= $field.'=?';
  72.       $values []= $this->fields[ $field ];
  73.     }
  74.     $set = join( ", ", $sets );
  75.     $values []= $this->id;
  76. $sql = 'UPDATE '.$this->table.' SET '.$set.
  77.   ' WHERE '.$this->table.'_id=?';
  78.     $sth = $db->prepare( $sql );
  79.     $db->execute( $sth, $values );
  80.   }
  81.   function delete()
  82.   {
  83.     global $db;
  84.     $sth = $db->prepare(
  85. 'DELETE FROM '.$this->table.' WHERE '.
  86. $this->table.'_id=?'
  87.     );
  88.     $db->execute( $sth,
  89.       array( $this->id ) );
  90.   }
  91.   function delete_all()
  92.   {
  93.     global $db;
  94.     $sth = $db->prepare( 'DELETE FROM '.$this->table );
  95.     $db->execute( $sth );
  96.   }
  97. }
  98. class Book extends DBObject
  99. {
  100.   function __construct()
  101.   {
  102.   parent::__construct( 'book',
  103.     array( 'author', 'title', 'publisher' ) );
  104.   }
  105. }
  106. $book = new Book( );
  107. $book->delete_all();
  108. $book->{'title'} = "PHP Hacks";
  109. $book->{'author'} = "Jack Herrington";
  110. $book->{'publisher'} = "O'Reilly";
  111. $id = $book->insert();
  112. echo ( "New book id = $id\n" );
  113. $book->{'title'} = "Podcasting Hacks";
  114. $book->update();
  115. $book2 = new Book( );
  116. $book2->load( $id );
  117. echo( "Title = ".$book2->{'title'}."\n" );
  118. $book2->delete( );
  119. ?>
复制代码
底部的测试代码只演示了这个语法干净了多少。要得到图书的书名,只需得到 title 成员变量。这个变量会调用对象的 __get 方法,在散列表中查找 title 条目并返回。

现在就得到了单个动态的数据库访问类,它能够让自己适应到数据库中的任何表。

返回列表