ThinkPHP---thinkphp模型(M)

2018/03/29 00:05
阅读数 209

(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)拓展里作总结

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部