『Web 2.0 Development in Practice』の著者である Quentin Zervaas は、本の中で単純な PHP データ アクセス オブジェクトについて言及しました。
- /**
- * DatabaseObject
- *
- * データベーステーブル内のデータを簡単に操作するために使用される抽象クラス
- * 単純なロード/保存/削除メソッドを介して
- */
- abstract class DatabaseObject
- {
- const TYPE_TIMESTAMP = 1;
- const TYPE_BOOLEAN = 2;
- protected static $types = array(self::TYPE_TIMESTAMP, self ::TYPE_BOOLEAN);
- private $_id = null;
- private $_properties = array();
- protected $_db = null;
- protected $_table = '';
- protected $_idField = '';
- public function __construct(Zend_Db_Adapter_Abstract $db, $table, $idField)
- {
- $this->_db = $db;
- $this->gt;_table = $table;
- $this->_idField = $idField;
- }
- public functionload($id, $field = null)
- {
- if (strlen($field) == 0)
- $field = $this->_idField;
-
- if ($field == $this- >_idField) {
- $id = (int) $id;
- if ($id return false;
- }
-
- $query = sprintf('select %s from %s where %s = ? ',
- join(', ', $this->getSelectFields()),
- $this->_table,
- $field);
-
- $query = $this->_db->quoteInto($query , $id);
-
- return $this->_load($query);
- }
-
- protected function getSelectFields($prefix = '')
- {
- $fields = array($prefix . $this->_idField);
- foreach ($this->_properties as $k => $v)
- $fields[] = $prefix 。 $k;
-
- return $fields;
- }
-
- 保護関数 _load($query)
- {
- $result = $this->_db->query($query);
- $row = $result-> fetch();
- if (!$row)
- return false;
-
- $this->_init($row);
-
- $this->postLoad();
-
- return true;
- }
-
- public function _init($row)
- {
- foreach ($this->_properties as $k => $v) {
- $val = $row[$k];
-
- switch ($v['type']) {
- case self::TYPE_TIMESTAMP:
- if (!is_null($val))
- $val = strtotime($val);
- Break;
- case self::TYPE_BOOLEAN:
- $val = (bool) $val;
- Break;
- }
-
- $this->_properties[$k]['value'] = $val;
- }
- $this->_id = (int) $row[$this->_idField];
- }
-
-
- public function save($useTransactions = true)
- {
- $update = $this->isSaved();
-
- if ($useTransactions)
- $this->db->beginTransaction();
-
- if ($update)
- $commit = $this->preUpdate();
- else
- $commit = $this->preInsert();
-
- if (!$commit) {
- if ($useTransactions)
- $this ->_db->rollback();
- return false;
- }
-
- $row = array();
-
- foreach ($this->_properties as $k => $v) {
- if ($update && !$v['updated'])
- continue;
-
- switch ($v['type']) {
- case self::TYPE_TIMESTAMP:
- if (!is_null($v ['値'])) {
- if ($this->_db インスタンスof Zend_Db_Adapter_Pdo_Pgsql)
- $v['値'] = date('Y-m-d H:i:sO', $v['値']);
- else
- $v['value'] = date('Y-m-d H:i:s', $v['value']);
- }
- Break;
-
- case self::TYPE_BOOLEAN:
- $v['value' ] = (int) ((bool) $v['value']);
- Break;
- }
-
- $row[$k] = $v['value'];
- }
-
- if (count($row ) > 0) {
- // 挿入/更新を実行します
- if ($update) {
- $this->_db->update($this->_table, $row, sprintf('%s = %d) ', $this->_idField, $this->getId()));
- }
- else {
- $this->_db->insert($this->_table, $row);
- $this->_id = $this->_db->lastInsertId($this-> _table, $this->_idField);
- }
- }
-
- // 内部 ID を更新します
-
- if ($commit) {
- if ($update)
- $commit = $this->postUpdate();
- else
- $commit = $this->postInsert();
- }
-
- if ($useTransactions) {
- if ($commit)
- $this->_db->commit();
- else
- $this-> ;_db->rollback();
- }
-
- return $commit;
- }
-
- public function delete($useTransactions = true)
- {
- if (!$this->isSaved())
- return false;
-
- if ($useTransactions)
- $this->_db->beginTransaction();
-
- $commit = $this->preDelete();
-
- if ($commit) {
- $this->_db- >delete($this->_table, sprintf('%s = %d', $this->_idField, $this->getId()));
- }
- else {
- if ($useTransactions)
- $this->db->rollback();
- return false;
- }
-
- $commit = $this->postDelete();
-
- $this->id = null;
-
- if ($ useTransactions) {
- if ($commit)
- $this->_db->commit();
- else
- $this->_db->rollback();
- }
-
- return $commit;
- }
-
- public function isSaved()
- {
- return $this->getId() > 0;
- }
-
- public function getId()
- {
- return (int) $this->gt;_id;
- }
-
- public function getDb()
- {
- return $this->gt;_db;
- }
-
- public function __set($name, $value)
- {
- if (array_key_exists($name, $this->_properties)) {
- $this->_properties[$name]['value'] = $value;
- $ this->_properties[$name]['updated'] = true;
- return true;
- }
-
- return false;
- }
-
- public function __get($name)
- {
- return array_key_exists($name, $this ->_プロパティ)? $this->_properties[$name]['value'] : null;
- }
-
- protected function add($field, $default = null, $type = null)
- {
- $this->_properties[$フィールド] = array('value' => $default,
- 'type' => in_array($type, self::$types) ? $type : null,
- 'updated' => false);
- }
-
- 保護関数 preInsert()
- {
- return true;
- }
-
- 保護関数 postInsert()
- {
- return true;
- }
-
- 保護関数 preUpdate()
- {
- return true;
- }
-
- 保護関数 postUpdate ()
- {
- return true;
- }
-
- 保護関数 preDelete()
- {
- return true;
- }
-
- 保護関数 postDelete()
- {
- return true;
- }
-
- 保護関数 postLoad()
- {
- return true;
- }
-
- public static function BuildMultiple($db, $class, $data)
- {
- $ret = array();
-
- if (!class_exists($class))
- throw new Exception('未定義クラス指定された: ' 。 $class);
-
- $testObj = new $class($db);
-
- if (!$testObj instanceof DatabaseObject)
- throw new Exception('クラスは DatabaseObject から拡張されていません');
-
- foreach ($data as $ row) {
- $obj = new $class($db);
- $obj->_init($row);
-
- $ret[$obj->getId()] = $obj;
- }
-
- return $ret;
- }
- }
-
复制代
- class DatabaseObject_User extends DatabaseObject
- {
- static $userTypes = array('member' => 'メンバー',
- 'administrator' => '管理者');
-
- public $profile = null;
- public $_newPassword = null;
-
- public function __construct($db)
- {
- parent::__construct($db, 'users', 'user_id');
-
- $this->add('username' );
- $this->add('パスワード');
- $this->add('user_type', 'member');
- $this->add('ts_created', time(), self: :TYPE_TIMESTAMP);
- $this->add('ts_last_login', null, self::TYPE_TIMESTAMP);
-
- $this->profile = new Profile_User($db);
- }
-
- 保護関数 preInsert()
- {
- $this->_newPassword = Text_Password::create(8);
- $this->password = $this->_newPassword;
- return true;
- }
-
- protected function postLoad()
- {
- $this ->profile->setUserId($this->getId());
- $this->profile->load();
- }
-
- 保護された関数 postInsert()
- {
- $this-> profile->setUserId($this->getId());
- $this->profile->save(false);
-
- $this->sendEmail('user-register.tpl');
- return true;
- }
-
- 保護関数 postUpdate()
- {
- $this->profile->save(false);
- return true;
- }
-
- 保護関数 preDelete()
- {
- $this->gt; profile->delete();
- return true;
- }
-
- public function sendEmail($tpl)
- {
- $templater = new Templater();
- $templater->user = $this;
-
- // フェッチ電子メールの本文
- $body = $templater->render('email/' . $tpl);
-
- // 最初の行から件名を抽出します
- list($subject, $body) = preg_split('/r|n/', $body, 2);
-
- // 設定して送信します電子メール
- $mail = new Zend_Mail();
-
- // 「宛先」行に宛先アドレスとユーザーのフルネームを設定します
- $mail->addTo($this->profile->email ,
- rim($this->profile->first_name . ' ' .
- $this->profile->last_name));
-
- // 設定から管理者の詳細を取得します
- $mail- >setFrom(Zend_Registry::get('config')->email->from->email,
- Zend_Registry::get('config')->email->from->name);
-
- // 件名と本文を設定してメールを送信します
- $mail->setSubject(trim($subject));
- $mail->setBodyText(trim($body));
- $mail->send ();
- }
-
- public function createAuthIdentity()
- {
- $identity = new stdClass;
- $identity->user_id = $this->getId();
- $identity->username = $this-> ;username;
- $identity->user_type = $this->user_type;
- $identity->first_name = $this->profile->first_name;
- $identity->last_name = $this-> profile->last_name;
- $identity->email = $this->profile->email;
-
- return $identity;
- }
-
- public function loginSuccess()
- {
- $this->ts_last_login = time();
- unset($this->profile->new_password);
- unset($this->profile->new_password_ts);
- unset($this->profile->new_password_key);
- $this->save();
-
- $message = sprintf('%s ユーザー %s からのログイン試行に成功しました',
- $_SERVER['REMOTE_ADDR'],
- $this->username);
-
- $logger = Zend_Registry::get('logger');
- $logger->notice($message);
- }
- static public function LoginFailure($username, $code = '')
- {
- switch ($code) {
- case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
- $reason = '不明なユーザー名';
- Break;
- case Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS:
- $reason = 'このユーザー名を持つ複数のユーザーが見つかりました';
- Break;
- case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
- $reason = '無効なパスワード';
- Break;
- default:
- $reason = '';
- }
-
- $ message = sprintf('%s ユーザー %s からのログイン試行に失敗しました',
- $_SERVER['REMOTE_ADDR'],
- $username);
-
- if (strlen($reason) > 0)
- $message .= sprintf( ' (%s)', $reason);
-
- $logger = Zend_Registry::get('logger');
- $logger->warn($message);
- }
-
- public function fetchPassword()
- {
- if (!$this->isSaved())
- return false;
-
- // 新しいパスワードプロパティを生成します
- $this->_newPassword = Text_Password::create(8);
- $this->profile-> new_password = md5($this->_newPassword);
- $this->profile->new_password_ts = time();
- $this->profile->new_password_key = md5(uniqid() .
- $this- >getId() .
- $this->_newPassword);
-
- // 新しいパスワードをプロファイルに保存して電子メールを送信
- $this->profile->save();
- $this->sendEmail ('user-fetch-password.tpl');
-
- return true;
- }
-
- public functionconfirmNewPassword($key)
- {
- // 有効なパスワードリセットデータが設定されていることを確認してください
- if (!isset($this- >プロフィール->新しいパスワード)
- || !isset($this->profile->new_password_ts)
- || !isset($this->profile->new_password_key)) {
-
- return false;
- }
-
- // パスワードが 1 日以内に確認されるかどうかを確認します
- if (time() - $this->profile ->new_password_ts > 86400)
- return false;
-
- // キーが正しいことを確認します
- if ($this->profile->new_password_key != $key)
- return false;
-
- //有効です。新しいパスワードを使用するようにアカウントを更新します
-
- // new_password は既に md5 であるため、ローカル セッターをバイパスします
- parent::__set('password', $this->profile->new_password);
-
- unset ($this->profile->new_password);
- unset($this->profile->new_password_ts);
- unset($this->profile->new_password_key);
-
- // 最後に保存します更新されたユーザー レコードと更新されたプロファイル
- return $this->save();
- }
-
- public function usernameExists($username)
- {
- $query = sprintf('select count(*) as num from %s where username = ?',
- $this->_table);
-
- $result = $this->_db->fetchOne($query, $username);
-
- return $result > 0;
- }
-
- static public function IsValidUsername($username)
- {
- $validator = new Zend_Validate_Alnum();
- return $validator->isValid($username);
- }
-
- public function __set($name, $ value)
- {
- switch ($name) {
- case 'password':
- $value = md5($value);
- Break;
-
- case 'user_type':
- if (!array_key_exists($value, self::$ userTypes))
- $value = 'member';
- Break;
- }
-
- returnparent::__set($name, $value);
- }
- }
- ?>
复制代
|