插件数据存储(2):自建数据表
如果上面的 Storage 数据存储方式无法满足更复杂的数据结构存储要求,插件可以自建数据库表存储数据。
创建插件数据表
利用上面提到的【事件回调】机制在自定义的 callback 函数中实现创建插件自己的表,下面给出一个简单的示例。
<?php
!defined('EMLOG_ROOT') && exit('access denied!');
// 初始化插件数据表
function callback_init() {
$db = MySql::getInstance();
$charset = 'utf8mb4';
$type = 'InnoDB';
$table = DB_PREFIX . 'stats';
$add = "ENGINE=$type DEFAULT CHARSET=$charset;";
$sql = "
CREATE TABLE IF NOT EXISTS `$table` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`gid` int(11) unsigned NOT NULL,
`title` varchar(255) NOT NULL default '',
`views` bigint(11) unsigned NOT NULL default 0,
`comments` bigint(11) unsigned NOT NULL default 0,
`date` date NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `date_gid` (`date`,`gid`)
)" . $add;
$db->query($sql);
}
// 插件删除时删除插件数据表
function callback_rm() {
$sql = "DROP TABLE IF EXISTS `" . DB_PREFIX . "stats`";
$db = MySql::getInstance();
$db->query($sql);
}
下面PHP代码是一个完整的维护插件自建数据库表的 callback 示例,可以直接用于自己插件 xxxx_callback.php ,修改对应建表语句即可。
<?php
/**
* 插件回调
*/
!defined('EMLOG_ROOT') && exit('error!');
/**
* 插件激活回调
*/
function callback_init(){
Init_Database_Callback::instance()->pluginInit();
}
/**
* 插件更新回调
*/
function callback_up(){
Init_Database_Callback::instance()->pluginUp();
}
/**
* 插件删除回调
*/
function callback_rm(){
Init_Database_Callback::instance()->pluginRm();
}
/**
* 数据表操作类
*/
class Init_Database_Callback {
//实例
private static $instance;
//数据库实例
private $db;
//数据表配置
private $option = [
//数据表名称
"tableName" => DB_PREFIX."toEverColor_list",
//卸载插件是否删除数据表 - true/false 对应 删除/不删除 默认为false(不删除)
"checkDeleteTable" => false,
//数据表字段信息,字段=>sql语句,请勿写错,程序根据这个来创建和检测字段
"fieldData" => [
"id" => "`id` int(50) NOT NULL AUTO_INCREMENT",
"gid" => "`gid` int(50) NOT NULL COMMENT '文章ID'",
"color" => "`color` varchar(200) DEFAULT NULL COMMENT '颜色'",
"weight" => "`weight` enum('n','y') DEFAULT 'n' COMMENT '是否加粗(默认不加粗)'",
"font_size" => "`font_size` int(50) DEFAULT NULL COMMENT '字号'",
"line_through" => "`line_through` enum('n','y') DEFAULT 'n' COMMENT '删除线'",
]
];
/**
* 私有构造函数,保证单例
*/
private function __construct(){
//数据库实例赋值
$this->db = Database::getInstance();
}
/**
* 单例入口
*/
public static function instance(){
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
/**
* 检测数据表是否存在
*/
public function checkDataTable() {
if (isset($this->option['tableName'])) {
$query = $this->db->query("SHOW TABLES LIKE '{$this->option['tableName']}'");
if ($this->db->num_rows($query) > 0) {
return true;
}
return false;
}
return false;
}
/**
* 检测数据表中字段是否存在 - 指定字段名
*/
public function checkDataField($fieldName = '') {
if (!empty($fieldName) && $this->checkDataTable()) {
$query = $this->db->query("SHOW COLUMNS FROM {$this->option['tableName']} LIKE '{$fieldName}'");
if ($this->db->num_rows($query) > 0) {
return true;
}
return false;
}
return false;
}
/**
* 数据表创建函数
*/
private function addDataTable() {
if (!empty($this->option) && is_array($this->option) && isset($this->option['fieldData']) && is_array($this->option['fieldData'])) {
$sql = "CREATE TABLE IF NOT EXISTS {$this->option['tableName']} (";
foreach ($this->option['fieldData'] as $field => $fieldSql) {
$sql .= $fieldSql . ',';
}
$sql .= " PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='标题改色表';";
$this->db->query($sql);
}
}
/**
* 检测数据表字段是否存在,不存在则创建字段
*/
private function addDataTableField() {
if (!empty($this->option) && is_array($this->option) && isset($this->option['fieldData']) && is_array($this->option['fieldData'])) {
$preForeachData = '';
foreach ($this->option['fieldData'] as $field => $fieldSql) {
if (!$this->checkDataField($field)) {
$after = !empty($preForeachData) ? " AFTER {$preForeachData}" : '';
$this->db->query("ALTER TABLE {$this->option['tableName']} ADD COLUMN {$fieldSql}{$after}");
}
$preForeachData = $field;
}
}
}
/**
* 插件启用执行函数
*/
public function pluginInit() {
if ($this->checkDataTable()) {
$this->addDataTableField();
} else {
$this->addDataTable();
}
}
/**
* 插件更新执行函数
*/
public function pluginUp() {
$this->addDataTableField();
}
/**
* 插件卸载执行函数
*/
public function pluginRm() {
if (isset($this->option['checkDeleteTable']) && $this->option['checkDeleteTable'] === true) {
$this->db->query("DROP TABLE {$this->tableName}");
}
}
}
读取插件数据表
<?php
// 读取插件数据
function getDetail($id) {
$db = MySql::getInstance();
$row = $db->once_fetch_array("SELECT * FROM " . DB_PREFIX . "stats WHERE id = " . $id);
$row['xxxx']
……
}