实现功能:
对数据表的读要缓存起来,对数据表的写需要清除缓存.
数据表根据属性字段来决定是否缓存
可以更换数据库链接方式,比如可以随时更换为mysql或mysqli()
当插入数据时给出一个通知或者提示,可以外部配置通知
一.数据操作接口
/** * Interface db */ interface dbInterface { // 此处为简便起见,只定义读取所有记录和写入记录 public function all(); public function create(array $attributes); }
二.数据库实现类(单例模式)
1.mysqli
class DbMySQLi implements dbInterface { private $link; private static $instance; private $table; private function __construct() { $this->link = mysqli_connect(‘localhost‘, ‘root‘, ‘root‘, ‘test‘); } public static function getInstance() { if (is_null(self::$instance)) { self::$instance = new self(); } return self::$instance; } public function setTable($table) { $this->table = $table; } /** * @return array|null */ public function all() { $res = mysqli_query($this->link, "select * from {$this->table}"); $data = []; while ($row = mysqli_fetch_assoc($res)) { $data[] = $row; } return $data; } /** * @param array $attributes * @return bool|mysqli_result */ public function create(array $attributes) { $keys = array_keys($attributes); $values = array_values($attributes); foreach ($keys as $key => $val) { $keys[$key] = "`{$val}`"; } foreach ($values as $key => $val) { $values[$key] = "‘{$val}‘"; } $insertKey = implode(‘,‘, $keys); $insertValue = implode(‘,‘, $values); mysqli_query($this->link, "insert into {$this->table}($insertKey) values({$insertValue})"); return mysqli_insert_id($this->link); } public function closeLink() { if ($this->link) { mysqli_close($this->link); } } }
2.mysql
class DbMySQL implements dbInterface { private $link; private static $instance; private $table; private function __construct() { $this->link = mysql_connect(‘localhost‘, ‘root‘, ‘root‘, ‘test‘); } public static function getInstance() { if (is_null(self::$instance)) { self::$instance = new self(); } return self::$instance; } public function setTable($table) { $this->table = $table; } /** * @return array|null */ public function all() { $res = mysql_query("select * from {$this->table}", $this->link); $data = []; while ($row = mysql_fetch_assoc($res)) { $data[] = $row; } return $data; } /** * @param array $attributes * @return bool|mysqli_result */ public function create(array $attributes) { $keys = array_keys($attributes); $values = array_values($attributes); foreach ($keys as $key => $val) { $keys[$key] = "`{$val}`"; } foreach ($values as $key => $val) { $values[$key] = "‘{$val}‘"; } $insertKey = implode(‘,‘, $keys); $insertValue = implode(‘,‘, $values); mysql_query("insert into {$this->table}($insertKey) values({$insertValue})", $this->link); return mysql_insert_id($this->link); } public function closeLink() { if ($this->link) { mysql_close($this->link); } } }
三.配置类
class Config { const DB_TYPE = ‘mysql‘; }
四.cache接口
interface Cache { public function clearCache(); public function setCache($data); public function getCache(); public function getKey(); }
文件缓存实现,此处用trait实现:
trait FileCacheTrait { public function clearCache() { @unlink($_SERVER[‘DOCUMENT_ROOT‘] . ‘/cache-‘ . $this->getKey() . ‘.php‘); } public function setCache($data) { $file = $_SERVER[‘DOCUMENT_ROOT‘] . ‘/cache-‘ . $this->getKey() . ‘.php‘; $cache = ‘<?php‘ . "\n"; $cache .= ‘return ‘; $cache .= var_export($data, true); $cache .= ‘;‘; file_put_contents($file, $cache); } public function getCache() { $file = $_SERVER[‘DOCUMENT_ROOT‘] . ‘/cache-‘ . $this->getKey() . ‘.php‘; if (is_file($file)) { return require $file; } return false; } public function getKey() { return md5($_SERVER[‘PHP_SELF‘] . ‘?‘ . $_SERVER[‘QUERY_STRING‘]); } }
五.通知(观察者)
接口:
interface ObserverInterface { public function fire(Model $model); }
实现:
class Observer implements ObserverInterface { public function fire(Model $model) { $model = $model->model(); echo "创建{$model->name}, id:{$model->id}"; } }
六.Model虚拟类:通用数据操作
abstract class Model { protected $observers = []; //被观察者数组 protected $db; protected $model; protected $cache = false; public function __construct() { // 简单工厂模式 if (Config::DB_TYPE == ‘mysql‘) { $this->db = DbMySQLi::getInstance($this->table()); } else { $this->db = DbMySQL::getInstance($this->table()); } $this->db->setTable($this->table()); } public function all() { if ($this->cache && $cache = $this->getCache()) { return $cache; } $data = $this->db->all(); if ($this->cache) { $this->setCache($data); } return $data; } public function create(array $attributes) { $insertId = $this->db->create($attributes); // 清除缓存 if ($this->cache) { $this->clearCache(); } $this->fill(array_merge($attributes, [‘id‘ => $insertId])); // 如果有设置created被观察者,直接调用 if (isset($this->observers[‘created‘])) { $this->observers[‘created‘]->fire($this); } return $insertId; } public function __destruct() { $this->db->closeLink(); } public function addObserver($key, ObserverInterface $observer) { $this->observers[$key] = $observer; } public function fill(array $attributes) { $this->model = (object) $attributes; } public function model() { return $this->model; } abstract public function table(); }
七.model实现类
class User extends Model implements Cache { // 配置缓存可用 protected $cache = true; use FileCacheTrait; public function table() { return ‘user‘; } }
八.App类:从外部负责给model绑定被观察者
class App { public static function observer(Model $model) { $model->addObserver(‘created‘, new Observer($model)); } }
调用:
$user = new User(); App::observer($user); $user->create([‘name‘ => ‘test‘]);
附加:
如果要用闭包调用,则Model类对应部分改为:
// 如果有设置created被观察者,直接调用 if (isset($this->observers[‘created‘])) { if ($this->observers[‘created‘] instanceof Closure) { call_user_func($this->observers[‘created‘], $this); } else { $this->observers[‘created‘]->fire($this); } }
App改为:
class App { public static function observer(Model $model) { $model->addObserver(‘created‘, function () use($model) { echo "创建{$model->model()->name}, id:{$model->model()->id}"; }); } }