数据模型
浏览数 111224
最后修改时间
数据模型是操作数据库的类,简称为“模型”,符合类的通用规则,模型的类名需要以 model_ 作为前缀,或者驼峰式以model为前缀,可以放在 /model 目录里,也可以放在 /helper目录里,你可以这两个目录之间随意的移动,不会影响程序的正常运行。如果你的系统文件不多,建议放在 /helper 目录里,这样可以得到更快的执行速度。
大多模型是与数据库直接打交道的,因此继承基类model(文件是/system/helper/model.php),继承后即刻拥有常用的数据表操作方法。当然你也可以不继承基类model,识情况而定。
数据库连接方式
YiluPHP提倡只用一种最常用的、最优的方案,这在数据库的使用就有体现,YiluPHP官方只提供MySQL数据库的合作方案,PHP与MySQL有多种连接方式,YiluPHP官方只提供PDO的连接方式,使用PDO的预编译功能,可以有效得避免SQL注入的漏洞。如果你的PHP没有开启PDO模块,记得开启哦,可以网上搜索 “PHP安装PDO模块的方法”。
配置数据库
需要使用MySQL数据库,你只要在配置文件(/config/app.php)中配置你的数据库连接信息即可。因各个(开发、测试、线上)环境中的数据库连接信息会不一样,建议你把数据库信息单独在项目目录外的文件中,然后使用 include 或 require 引入,并合并到全局变量 $config 中。这样做的好处有:
一、数据库信息不会进入SVN或git库中,线上的数据库信息不会被泄露;
二、数据库信息不会在项目的文件中,避免误删。
在 $config['mysql'] 中有默认的数据库连接名称为 default,你可以把它修改成你的可用的数据库连接信息。另外YiluPHP支持同时配置多个数据库,和 default 一样,你可以定义多个你自己的数据库连接名称,并配置上相应的信息。然后在具体模型类中设置此类所需的数据库连接名称。
$config = [
...
'mysql' => [
//default为默认的数据库连接名
'default' => [
'dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=yiluuc',
'username' => 'root', //你的数据库登录名
'password' => 'yiluPHP@2017', //你的数据库登录密码
'charset' => 'utf8mb4',
'option' => [],
],
//你可以自定义一个你想要的连接名称
'your_db_name' => [
'dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=my_db_name',
'username' => 'root', //你的数据库登录名
'password' => 'yiluPHP@2017', //你的数据库登录密码
'charset' => 'utf8mb4',
'option' => [],
],
],
...
];
class model_users extends model
{
//表名
protected $_table = 'users';
//数据库连接名
protected $_connection = 'default';
//存储单例
private static $_instance = null;
/**
* 获取单例
* @return model|null 返回单例
*/
public static function I(){
if (!static::$_instance){
return static::$_instance = new self();
}
return static::$_instance;
}
...
}
class model_blog extends model
{
//表名
protected $_table = 'blog';
//使用你自定义的数据库连接名
protected $_connection = 'your_db_name';
//存储单例
private static $_instance = null;
/**
* 获取单例
* @return model|null 返回单例
*/
public static function I(){
if (!static::$_instance){
return static::$_instance = new self();
}
return static::$_instance;
}
...
}
使用PHP操作数据库
配置完数据库连接信息之后,按照上一步创建数据模型类,只要模型类继承了model基类,那它就自带一些常用的增删改查功能了。无需要额外写引入类文件的代码,你可以在任务地方调用模型。
//根据id查询一条数据
$blog_info = model_blog::I()->find_table(['id'=>888], '*');
//选择所有type为1的数据,按创建时间倒序排
$data = model_blog::I()->select_all(['type'=>1],'create_time DESC','*');
//分页获取数据,这里获取第1页,每页20条,按创建时间倒序排
$data_list = model_blog::I()->paging_select([],1,20,'create_time DESC');
//往博客表中插入一条数据
$data = [
'title' => '博客标题',
'content' => '博客内容',
'create_time' => time(),
];
model_blog::I()->insert_table($data);
//获取两天内的博客数据,按创建时间倒序排序
$where = [
'create_time' => [
'symbol' => '>=',
'value' => strtotime('-2 days'),
],
];
$data_list = model_blog::I()->select_all($where, 'create_time DESC', '*');
//获取所有type等于1和2的数据,按创建时间倒序排序
$where = [
'type' => [
'symbol' => 'IN',
'value' => [1,2],
],
];
$data_list = model_blog::I()->select_all($where,'create_time DESC','*');
//获取所有title中包含“关键词”的数据,按创建时间倒序排序
$where = [
'title' => [
'symbol' => 'LIKE',
'value' => '%关键词%',
],
];
$data_list = model_blog::I()->select_all($where,'create_time DESC','*');
在model基类中还有其它一些操作方法,可以查看 /system/helper/model.php 的源码了解,这里再提两个使用原生SQL的方法,一个查询方法和一个修改方法
//查询类SQL的操作方法
$table = model_blog::I()->get_table();
$sql = <<<sql
SELECT * FROM `$table` WHERE `title` LIKE :title LIMIT 10
sql;
$args = ['title'=>'关键词%'];
$data_list = model_blog::I()->select_sql($sql, $args);
//修改类SQL的操作方法
$table = model_demo::I()->get_table();
$sql = <<<sql
UPDATE `$table` SET `status`=1 WHERE id=:id
sql;
model_blog::I()->execute_sql($sql, ['id'=>888]);
模型方法的命名约定
另外,model 的方法名有一个约定的规范,遵照这个规范可以让你轻易得找到你想要的方法,如下:
/*
* 新增一条记录的方法名使用insert_开头
* 新增多条记录的方法名使用add_开头
* 新增(已存在则更新)一条记录的方法名使用save_开头
* 新增(已存在则更新)多条记录的方法名使用store_开头
* 删除一条记录的方法名使用delete_开头
* 删除多条记录的方法名使用destroy_开头
* 更新一条记录的方法名使用update_开头
* 更新多条记录的方法名使用change_开头
* 查询一条记录的方法名使用find_开头
* 查询一条统计数据的方法名使用count_开头
* 查询多条记录的方法名使用select_开头
* 分页查询的方法名使用paging_开头
*/
分库分表
YiluPHP 的 model 实现了两种分表方式,第一种是按id的后两位分为100个表,分表名的后缀为下划线加id的后两位整数。第二种是按时间和表数据的数量自动分表。
第一种:按主键id的后两位分为100个表
第二种:按时间和表数据的数量自动分表
需要创建一个管理分表的数据表,SQL在这里:
/document/default_table.sql
CREATE TABLE `sub_table_manage` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`main_table` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '主表名称',
`sub_table` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '分表名称',
`connection` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '数据库连接的名称',
`model_name` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '模型类的名称',
`count` int unsigned NOT NULL DEFAULT '0' COMMENT '表中的数据量每天更新一次',
`start_time` int unsigned NOT NULL COMMENT '启用时间',
`end_time` int NOT NULL DEFAULT '0' COMMENT '结束时间',
`create_time` int unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_unique` (`main_table`,`sub_table`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='主表和分表的管理';
class user extends model
{
//表名,不包含分表名
protected $_table = 'user';
//数据库连接名
protected $_connection = 'default';
/**
* 拆分表的方式
* null表示不拆分
* last_two_digits表示根据(如ID)末尾2位数拆分成100个表
* time_and_quantity表示按时间和数量分表,在一定时间内数量未达到 $_max_quantity_per_table 设置的数量时不分表,否则分表,每天凌晨4点检测是否需要分表,
* 如果需要分表会设置好第二天开始需要使用的表,所以表中的最终数据量会比预设的数值多一天的数据量
*/
protected $_split_method = 'time_and_quantity';
//单表超过5百万条数据就分表
public $_max_quantity_per_table = 5000000;
....
}
创建系统的定时任务:创建新的分表,按照目前实现规则,只需要在每天的凌晨3点半和4点各执行一次就行
运行方式如:/usr/local/php8.0.2/bin/php /data/web/www.yiluphp.com/yilu create_sub_table