<?php
class DataObject {
private $changedFields = array(); // 更新了的字段列表
private $data = array(); // 從PDO取得的一條記錄
// 以上幾個字段都是本類私有的,因此子類即便是定義同名的屬性
// 或者將同名屬性關聯到數據表的某個字段中,也絲毫不會影響本類的這些變量
function __get($property) {
if (isset($this::$_propertyList[$property])) {
return $this->data[$this::$_propertyList[$property]]; // 根據PHP屬性名直接訪問字段
} else {
return $this->$property; // 如果沒有對應的屬性,則顯示PHP默認的錯誤信息
}
}
function __set($property, $value) {
if (isset($this::$_propertyList[$property])) {
$field = $this::$_propertyList[$property];
$this->data[$field] = $value; // 更新$_data[字段名]的值
// 記錄更新了的字段
if (!in_array($field, $this->changedFields)) {
array_push($this->changedFields, $field);
}
} else {
$this->data[$property] = $value; // 將不存在的屬性全部統一存入$_data
}
}
public function delete() {
}
public function insert() {
global $dbh;
if (empty($this->changedFields)) {
$stmt = $dbh->prepare('INSERT INTO ' . $this::$_table['name'] . ' VALUES ()');
$rs = $stmt->execute();
} else {
$fields = join(', ', $this->changedFields);
$placeholders = str_repeat('?, ', count($this->changedFields) - 1) . '?';
$sql = 'INSERT INTO ' . $this::$_table['name'] . " ($fields) VALUES ($placeholders)";
$stmt = $dbh->prepare($sql);
$param = 1;
foreach ($this->changedFields as $field) {
$stmt->bindValue($param++, $this->data[$field]);
}
$rs = $stmt->execute();
}
if ($rs) {
$this->changedFields = array();
// 獲取生成的主鍵字段
if (is_string($this::$_table['key'])) {
$this::$_table['key'] = array($this::$_table['key']);
}
$sql = 'SELECT ' . join(', ', $this::$_table['key']) . ' FROM ' . $this::$_table['name'];
}
return $rs;
}
public function update() {
global $dbh;
if (empty($this->changedFields) || empty($this::$_table['key'])) {
return false;
}
// 禁止直接更新主鍵字段,如果必須要更新主鍵字段,請手動執行SQL語句
if (is_string($this::$_table['key'])) {
$this::$_table['key'] = array($this::$_table['key']);
}
if (array_intersect($this->changedFields, $this::$_table['key'])) {
trigger_error("Forbidden to update the primary key of a row", E_USER_WARNING);
return false;
}
$sql = 'UPDATE ' . $this::$_table['name'] . ' SET ';
$sql .= join(' = ?, ', $this->changedFields) . ' = ? WHERE ';
$sql .= join(' = ? AND ', $this::$_table['key']) . ' = ?';
$stmt = $dbh->prepare($sql);
$param = 1;
foreach ($this->changedFields as $field) {
$stmt->bindValue($param++, $this->data[$field]);
}
foreach ($this::$_table['key'] as $key) {
$stmt->bindValue($param++, $this->data[$key]);
}
$rs = $stmt->execute();
if ($rs) {
$this->changedFields = array(); // 若成功就清空字段列表
}
return $rs;
}
}
// 相冊類
class Album extends DataObject {
protected static $_table = array('name' => 'Albums', 'key' => 'AlbumID'); // 設置PHP類對應的數據表的名稱,以及數據表裡所有主鍵的字段名稱
protected static $_propertyList = array('id' => 'AlbumID', 'artist' => 'AlbumArtist', 'title' => 'AlbumTitle'); // PHP類屬性名與數據表字段名的對應關係
// 獲取前$num個相冊對象的靜態方法
public static function GetSomeAlbums($num) {
global $dbh; // 調用外部變量$dbh
$arr = array();
$sql = "SELECT * FROM Albums WHERE AlbumID <= $num";
$stmt = $dbh->query($sql);
while ($album = $stmt->fetchObject('Album')) {
$arr[] = $album;
}
return $arr;
}
// 獲取指定標題的相冊的靜態方法
// 成功時返回Album對象,失敗時返回NULL
public static function GetAlbumByTitle($title) {
global $dbh;
$sql = "SELECT * FROM Albums WHERE AlbumTitle = ?";
$stmt = $dbh->prepare($sql);
$stmt->bindValue(1, $title);
$stmt->execute();
return $stmt->fetchObject('Album');
}
}
$dbh = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'test', DB_PASSWORD);
$some = Album::GetSomeAlbums(6); // 獲取前6個相冊
echo 'Num: ', count($some), '<br>';
echo $some[1]->title, '<br>'; // ->title被魔術方法_get自動重定向到->data['AlbumTitle']
echo $some[2]->artist, '<br>'; // ->artist被魔術方法_get自動重定向到->data['AlbumArtist']
// 請不要直接通過DataObject更新主鍵字段
$some[1]->id = 100;
$some[1]->update();
// 若要更新主鍵字段,請手動執行SQL語句
// 因為DataObject在更新記錄時依賴於主鍵字段
$sql = 'UPDATE Albums SET AlbumID = 100 WHERE AlbumID = ' . $some[2]->id;
//echo $sql, '<br>';
// 獲取指定標題的相冊
$dream = Album::GetAlbumByTitle('In My Dreams');
echo '<br>', $dream->artist, '<br>';
$abc = Album::GetAlbumByTitle('abc'); // 獲取一個不存在的相冊
if (!$abc) {
echo 'No such album!!!<br>';
}
// 添加一個相冊
/*$album = new Album();
$album->title = 'test title'; // 基類DataObject會自動記錄更新了哪些字段
$album->artist = 'test artist';
if ($album->insert()) {
printf('Inserted! ID = %d<br>', $album->id);
}*/
/*
// 添加空白相冊記錄
$album = new Album();
$album->insert();
*/
/*$stmt = $dbh->query('SELECT * FROM Albums WHERE AlbumID = 6');
$album = $stmt->fetchObject('Album'); // 所有的數據都會自動存入data數組中
if ($album) {
print_r($album); // 輸出$album對象的結構
echo '<br><b>Title: </b>';
echo $album->title;
// 更新字段
if ($album->title != 'New Title') {
$album->title = 'New Title';
if ($album->update($dbh)) {
echo '<p>Updated</p>';
}
}
} else {
// 記錄不存在
echo 'No such record!';
}*/
?>