ThinkPHP---thinkphp模型(M)
(1)配置数据库连接
数据库的连接配置可以在系统配置文件ThinkPHP/Conf/convention.php中找到
/* 数据库设置 */ 'DB_TYPE' => '', // 数据库类型,一般为MySQL 'DB_HOST' => '', // 服务器地址,本地开发时为localhost,远程为远程ip 'DB_NAME' => '', // 数据库名 'DB_USER' => '', // 用户名 'DB_PWD' => '', // 密码 'DB_PORT' => '', // 端口,3306.如果填写了MySQL,可以不填 'DB_PREFIX' => '', // 数据库表前缀。例如sp_user,前缀为sp。至于原因在文章里做了介绍 'DB_PARAMS' => array(), // 数据库连接参数 'DB_DEBUG' => TRUE, // 数据库调试模式 开启后可以记录SQL日志 'DB_FIELDS_CACHE' => true, // 启用字段缓存 'DB_CHARSET' => 'utf8', // 数据库编码默认采用utf8 'DB_DEPLOY_TYPE' => 0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) 'DB_RW_SEPARATE' => false, // 数据库读写是否分离 主从式有效 'DB_MASTER_NUM' => 1, // 读写分离后 主服务器数量 'DB_SLAVE_NO' => '', // 指定从服务器序号
找到后不能直接在系统配置文件里修改,应该放到对应配置文件里。配置文件除了系统配置文件外,还有分组/平台配置文件和应用配置文件。
那么数据库配置文件位置放到哪个层级的配置文件呢?
实际开发里,前台后台一般使用一个数据库,也就是说一个项目一个数据库,所以一个应用使用一个数据库,所以放到应用层级的配置文件Application\Common\Conf\config.php
里。
<?php return array( //'配置项'=>'配置值' /* 数据库设置 */ 'DB_TYPE' => 'mysql', // 数据库类型,除此外还有可能用到access,oracle,sqlite,db2 'DB_HOST' => 'localhost', // 服务器地址,若是远程服务器,则填写远程IP 'DB_NAME' => 'db_oa', // 数据库名 'DB_USER' => 'root', // 用户名 'DB_PWD' => 'root', // 密码 'DB_PORT' => '3306', // 端口 'DB_PREFIX' => 'sp_', // 数据库表前缀,设置时必须加下划线 );
(2)创建数据库和数据表
数据库名:db_oa
数据表名: sp_dept(department部门);
准备好sql语句:
create database db_oa;//创建数据库 use db_oa;//调用数据库 create table sp_dept( id int not null auto_increment, name varchar(50) not null, pid int not null default 0,//部门分上下级,pid只下级部门id sort int not null default 50,//排序 remark varchar(255),//备注说明 primary key(id) )engine=myisam default charset=utf8;//引擎myisam,Mysql的默认存储引擎
知识点:not null不为空;auto_increment自增;default默认;
这里除了通过命令行cmd创建,还可以使用Navicat Premium。它是一个可多重连接的数据库管理工具,它可让你以单一程序同时连接到MySQL、SQL Server、SQLite、Oracle、
PostgreSQL数据库,让管理不同类型的数据库更加方便。数据库/表的具体创建及使用我在文章Navicat使用方法里做了总结
(3)模型创建
1. 什么是模型?
模型是MVC中的M(model),作用负责与数据表的数据交互(CURD,即创建Create、更新Update、读取Retrieve和删除Delete操作)
2. 模型的创建
①命名规范:模型名+Model关键词+class.php(与控制器的命名规范大致相同:控制器名+Controller关键词+class.php)
注意:因为模型是用来操作数据表,所以模型实例化时肯定需要去关联一张表。因此模型名要求是不带前缀的表名,且首字母大写
②代码结构规范(与控制器类似)
第一步:声明命名空间;
第二部:引入父类模型Model.class.php;
第三部:声明并继承父类模型。
3. 案例
例如后期需要部门模型DeptModel.class.php实现对部门数据表sp_dept的操作,模型名的命名一般为关联的数据表表名去掉前缀。这里我在Admin/Model下创建模型文件
<?php namespace Admin\Model;//声明命名空间(分组\目录) use Think\Model;//引入父类模型(Think开头是因为Think.class.php文件的命名空间为Think) //声明并继承模型 class DeptModel extends Model{ } ?>
注意:空模型仍然可以进行数据表的(CURD操作),因为继承了父类模型,可以执行基本的操作增删改查,因为父类中已经封装好了CURD方法
(4)模型实例化(创建控制器,连接数据表)
模型的本质是类,类在使用时需要实例化操作。
1. 普通实例化
通过自己编写代码来new对象,$obj接受实例化结果,然后实例化类创建出一个对象。接下来在控制器里定义一个方法来实例化模型,使用普通方法实例化
创建部门控制器文件,Admin/Controller/DeptController.class.php:
<?php namespace Admin\Controller; use Think\Controller; class DeptController extends Controller{ public function dept(){ $model = new \Admin\Model\DeptModel(); dump($model); } } ?>
通过输出结果,发现模型在控制器里实例化的时候自动关联了数据表,为什么自动关联?
因为当前模型名字是表名去掉后缀。所以在控制器中进行实例化时,系统底层会自动关联上相关的数据表。虽然模型里没有前缀,但是配置信息里设置了数据表前缀
/* 数据库设置 */ 'DB_PREFIX' => 'sp_', // 数据库表前缀,设置时必须加下划线
2. 快速实例化方法
上述实例化方法虽然可以进行实例化操作,但使用麻烦,还需考虑命名空间。所以ThinkPHP为了简单快速高效开发,提供了两个快速方法(M和D)来实例化模型。
D方法:$obj = D(['模型名']);
上述表示实例化我们自己创建的模型(分组/Model目录中),除了自己创建的模型外还有父类模型(系统模型)。如果传递了模型名,则实例化指定的模型;若没有传递模型名或模型名不存在,则实例化系统模型(父类模型Model.class.php)
M方法:$obj = M(['不带前缀的表名']);
表示直接实例化父类模型,即系统模型(Think/Model.class.php)。若指定了表名,则实例化父类模型时,关联指定表;若没有传递参数则不关联表,不关联时一般用于执行原生的sql语句(M()->query(原生的sql语句))
D和M方法区别:实例化对象不同
案例:
①实例化自定义模型,其实例化结果与普通new方法一样
$model = D('Dept'); dump($model);
若不传参数实例化,则会实例化父类模型(系统模型)。结果与上诉不同,系统模型Tnink/Model位置不同,且没有关联表
$model = D(); dump($model);
②实例化父类模型
若传入了表名,则会在实例化时关联数据表
$model = M('dept');//这里传递了dept数据表,所以会在实例化时关联dept数据表
$model = M();//实例化父类模型,但不关联数据表 dump($model);
拓展:经典面试题:
①实例化方法中D方法和M方法区别?
实例化的对象不同。D方法将自定义的模式进行实例化,若自定义模型不存在,则实例化父类模型(系统模型),而M方法是直接实例化(父类)系统模型
②开发中如何选取实例化方法?
根据项目情况,若当前需要的操作在父类中已经封装好了,则直接实例化父类(M方法)。若父类中的方法不能满足开发需求,需要自定义方法,则可以使用D方法实例化自定义模型。一般的增删改查操作在父类模型里已经封装好了,直接使用M方法实例化即可
【五】CURD操作
模型操作数据表的基本操作
(1)增加操作
在MySQL里增加操作语句是insert...into...,但在ThinkPHP里系统封装好了模型里的方法add。
语法:$model->add(一维键值数组),注意:一维数组必须是一维的关联数组,且键必须和数据表的字段名匹配。如不匹配则在增加时会被ThinkPHP过滤掉
案例:往部门表里添加一条记录
public function dept(){ $model = M('dept'); //声明关联数组 $person = array( 'name'=>'人事部', 'pid'=>'0', 'sort'=>'1', 'remark'=>'这是人事部门' ); $result = $model -> add($person);//返回新增记录的主键id dump($result); }
补充:如何需添加多个记录?
①循环;
②addAll方法,语法:$model->addAll(二维数组),要求最里面的一维数组必须为关联数组(要求键名与数据表字段匹配),另外外层数组必须是从0开始的连续的索引数组
注意:虽然数组中顺序无关,但是要求子数据的第一条数组的键名顺序必须与数据表一致,后面的子数组键名顺序随意,因为后面的都会按照第一条的键名顺序填写
public function dept(){ $model = M('dept'); //声明关联数组 $person = array( array( 'remark'=>'这是人事部门2', 'name'=>'人事部2', 'pid'=>'0', 'sort'=>'1' ), array( 'remark'=>'这是人事部门1', 'name'=>'人事部1', 'pid'=>'0', 'sort'=>'1' ) ); $result = $model -> addAll($person);//返回新增记录的逐渐id dump($result); }
(2)修改操作
在MySQL里修改操作使用update table语句+where条件。在ThinkPHP中使用save方法,语法:$model->save(一维关联数组)
条件需要一维关联数组必须有主键信息(相当于where条件),若没有主键信息,则相当于批量修改。在ThinkPHP里,为了仿制误操作导致批量修改或删除,不允许批量操作
案例:使用save方法修改部门表中财务部门信息
public function dept(){ //实例化模型 $model = M('dept'); //声明关联数组 $change = array( 'id'=>2,//当前表得到主键,如果没有指定主键信息,则返回值为false。表示修改操作没有执行 'name'=>'修改2', 'remark'=>'修改备注' ); $result = $model -> save($change);//返回值表示收到影响的行数 dump($result); }
注意:必须有主键信息(相当于where条件),否则返回false
(3)查询操作
MySQL查询操作为select。在ThinPHP里系统封装了两个方法用于查询,select方法和find方法
select语法:①$model->$select(); 查询全部信息
②$model->select(id); 查询指定id的信息
③$model->select('id1,id2,id3,id4...'); 等价于MySQL的where id in('1,2,3,4'),表示查询指定id集合的信息
find语法:①$model->find(); 查询当前数据表的第一个信息,相当于limit 1;
②$model->find(id); 查询表里指定id的数据
区别:select方法返回值是二维数组,即使只查询到了一条记录也是返回二维数组;而find方法返回一维数组
案例:使用select和find方法查询部门表中的数据
public function select(){ //实例化模型 $model = M('dept'); //select查询
$result = $model->select();//查询所有 $result = $model->select('1');//查询id为1的记录
$result = $model->select('1,3,5');//查询id为1,3,5的记录 dump($result); }
select方法即使只查询一条数据,仍然会返回二维数组,如下
array(1) { [0] => array(5) { ["id"] => string(1) "1" ["name"] => string(3) "one" ["pid"] => string(1) "0" ["sort"] => string(2) "50" ["remark"] => string(9) "第一个" } }
对比find查询结果如下
array(5) { ["id"] => string(1) "1" ["name"] => string(3) "one" ["pid"] => string(1) "0" ["sort"] => string(2) "50" ["remark"] => string(9) "第一个" }
find查询:
public function select(){ //实例化模型 $model = M('dept'); //find查询 $result = $model->find();//返回第一条记录,相当于limit 1 $result = $model->find('2');//返回指定id所在的记录 dump($result); }
(4)删除操作
在MySQL中使用delete from语句删除,在ThinkPHP里系统封装好了delete方法删除记录
语法:
①$model->delete(); //因为ThinkPHP不支持没有指定主键的操作,所以该方法不支持
②$model->delete(id); 删除指定id对应的记录
③$model->delete('id1,id2,id3,...') 删除多个id对应的记录
注意:删除分两种物理删除、逻辑删除。
物理删除:真删除
逻辑删除:假删除,本质是修改操作。在数据表里定义一个状态字段status,取值0和1。当进行读取时只会读取状态值为1的数据,若用户点击删除,则会触发状态status转为0。从而在读取时获取不到,造成删除的假象。实际开发中也是常有逻辑删除(信息就是资源!!)
案例:使用delete进行删除操作(真删除)
public function del(){ //实例化模型 $model = M('dept'); //delete删除 $result = $model->delete();//返回false $result = $model->delete('1');//删除指定id的记录,返回影响行数 $result = $model->delete('1,2,3');//删除多个id的记录,返回影响行数 dump($result);
}
【六】Tp中的模型
具体在文章视频学习笔录---ThinkPHP---thinkphp模型(M)拓展里作总结