《TP5.0学习笔记---模型篇》

https://blog.csdn.net/self_realian/article/details/78596261php

1、什么是模型 thinkphp

为何咱们要在项目中使用模型,其实咱们知道,咱们能够直接在控制器中进行数据库的增、删、改、查,其实已经能基本完成咱们的需求,可是,为何还要有模型的存在呢? 数据库

好比说咱们如今要作一个用户注册的操做,用户注册咱们可能用两个表来保存用户的信息,一个是user表(保存用户基本信息),一个是user_info表(保存用户扩展信息,好比爱好等等),若是咱们如今直接在咱们的控制器中编写,那么咱们须要对数据库两个表进行操做,咱们就须要写两个db的方法来进行操做,咱们须要将这些方法进行封装,最后放在模型里,只要执行这个模型里的某一个方法,那么就会自动完成咱们全部操做的操做,也就是说,把咱们数据库完成同一件事情的操做,放在一个公共方法里,这样咱们在控制器里进行调用就会变得很方便。特别是代码复用的部分,咱们能够编写这样的方法,让咱们在任何地方可使用用户注册这个方法。那么下面就看看如何定义模型: 数组

首先在咱们的application/index/建立一个model目录,专门放模型文件,而后在model目录下建立一个User.php文件 浏览器

模型文件的命名规范: 首先咱们的模型名和咱们的表名要是对应的。好比咱们要写咱们数据库中的shulv_user表,那么咱们的模型名就是去掉前缀以后使用驼峰的命名方式,也就是User.php,当数据库中有这种包含下划线的表名时,去掉下划线,并将下划线后边的字母大写,即时模型名,shulv_user_info 对应模型名就是UserInfo,这样他就会自动对应到数据库中的表。下边写代码验证一下:安全

namespace app\index\controller;闭包

 

use think\Controller;app

use app\index\model\User;//使用咱们刚刚新建的那个模型函数

 

class Index extends Controller学习

{

    public function index()

    {

        $res = User::get(51);//经过get()方法,取出user表中的id=51的这条数据(如今能够不用知道为何使用get方法,后边会说)

        $res = $res->toArray();//将取出的数据转换成数组

        dump($res);

    }

}

  •  

你会发现,咱们没有在模型中的User.php中编写任何的代码,可是在控制器中use进来User模型以后,就能够直接使用静态方法,这是为何呢? 

由于在咱们的模型文件中的类都继承了think\Model这个类,think\Model中其实有这样的方法,这些方法,后边会说到。一样咱们还能够在控制器中使用new的方式

$user = new User();

        $res = $user::get(53);

        $res = $res->toArray();

        dump($res);

  •  

当咱们,不想经过use的方式将User模型引入进来的时候,咱们还能够经过下边的方法:

namespace app\index\controller;

 

use think\Controller;

//use app\index\model\User;//使用咱们刚刚新建的那个模型

use think\Loader;//经过引入think下的Loader类

class Index extends Controller

{

    public function index()

    {

        $user = Loader::model("User");//经过Loader下的model这个静态方法来引入对应模型

        $res = $user::get(52);

        $res = $res->toArray();

        dump($res);

 

    }

}

//说明:这种方式,是当咱们的控制器下有多个模型的时候,咱们使用这种方式,这样咱们就不用在使用每个模型的时候都use一下,咱们直接使用Loader::model()这种方法直接引入。另外,它还提供了一个助手函数model(),此时咱们连Loader类都不用引入了

/*

    $user = model("User");

    $res = $user::get(52);

    $res = $res->toArray();

    dump($res);

*/

 

//在这里建议你们使用前两种方式,由于助手函数式可能被覆盖掉的,固然这种状况不多发生,可是为了不,或者让咱们的代码可读性更高,建议你们使用第一种方式,也就是将须要的模型都use进来,经过它的静态方法来获取数据,这样咱们的代码看起来更清晰,咱们能够在最上边就看见咱们当前的控制器使用了哪些模型类,这样在后期维护中会变得很方便

  •  

2、经过模型进行数据查询

namespace app\index\controller;

 

use think\Controller;

use app\index\model\User;//使用咱们刚刚新建的那个模型

//use think\Loader;//经过引入think下的Loader类

class Index extends Controller

{

    public function index()

    {

        //以前咱们查询一条数据的时候是经过给get()方法传递一个主键来获取对应数据,咱们还能够传递一个闭包函数

        $res = User::get(function($query){//在这里边构造查询条件

            $query->where("id", "eq", 55);//这里条件的构造和前边的博客中说的同样(一样能够在后边继续添加链式方法)

        });

        $res = $res->toArray();

        dump($res);

    }

}

  •  

 

咱们还能够经过下边这种方法构造where条件

namespace app\index\controller;

 

use think\Controller;

use app\index\model\User;//使用咱们刚刚新建的那个模型

//use think\Loader;//经过引入think下的Loader类

class Index extends Controller

{

    public function index()

    {

        $res = User::where("id", 51)

            ->find();//一样咱们能够在后边添加更多的链式方法

        $res = $res->toArray();

        dump($res);

    }

}

/*

当咱们想获取表中的多条数据时,咱们可使用User::all();参数是主键名,可使用字符串的方式,也可使用数组的方式

$res = User::all("1,2,3");//这个时候返回的每一条记录都是一个对象,咱们就能够经过foreach进行遍历输出

//或$res = User::all([1,2,3]);

foreach($res as $value){

    dump($value->toArray());//这个时候咱们就会得到三条数据

}

 

//这个all()还能够接收一个闭包函数做为参数,来构造where条件

$res = User::all(function($query){

    $query->where("id", "<", 5); //一样能够添加更多的链式方法

});

 

*/

  •  

当咱们想要获取单独的一个字段,咱们知道Db类有一个value() 方法,模型咱们也能够这样

$res = User::where()->value("email");//直接返回的是字符串

dump($res);

//获取某一个字段那一列时

$res = User::column("email");//返回的是一个数组

  •  

3、使用模型添加数据 

在thinkphp,它的model为咱们提供了一个create()方法(静态方法),直接向数据库中插入数据

namespace app\index\controller;

 

use think\Controller;

use app\index\model\User;//使用咱们刚刚新建的那个模型

//use think\Loader;//经过引入think下的Loader类

class Index extends Controller

{

    public function index()

    {

       $res = User::create([

            'username'   =>  'shulv',

            'password'   =>  md5('shulv'),

            'email'      =>  'shulv@qq.com',

            'num'        =>  100

       ]);//它的返回结果依然是一个对象

       dump($res->id);//得到此时的自增id

       dump($res);

    }

}

  •  

 

namespace app\index\controller;

 

use think\Controller;

use app\index\model\User;//使用咱们刚刚新建的那个模型

//use think\Loader;//经过引入think下的Loader类

class Index extends Controller

{

    public function index()

    {

       // $res = User::create([

       //      'username'   =>  'shulv',

       //      'password'   =>  md5('shulv'),

       //      'email'      =>  'shulv@qq.com',

       //      'num'        =>  100

       //      'demo'       =>  15245

       // ]);//当咱们要插入一个表中并无的字段时,不传递第二个参数时,运行时会报错,说该字段不存在(此时数据库也并不会插入这条数据)

/*

    咱们知道,当前台传递数据时,每每直接传到$_POST中,咱们会将POST中全部的数据插入到表中,那么咱们就应该让它有的就插入表中,没有的就不插入,此时咱们就须要给它传入第二个参数"true"

*/

        $res = User::create([

            'username'   =>  'shulv1',

            'password'   =>  md5('shulv1'),

            'email'      =>  'shulv1@qq.com',

            'num'        =>  101,

            'demo'       =>  15245

       ],true);

 

       dump($res);

    }

}

  •  

 

当咱们仅容许添加指定的字段时,咱们能够将第二个参数传递一个数组,数组中的元素就是,你指定添加的字段

public function index()

    {

        $res = User::create([

            'username'   =>  'shulv2',

            'password'   =>  md5('shulv2'),

            'email'      =>  'shulv2@qq.com',

            'num'        =>  102,

            'demo'       =>  145

       ],['username','password']);

 

       dump($res->id);

    }

  •  

 

模型中还为咱们提供了一个save()方法来插入数据(若是咱们想使用save()就要先实例化咱们的模型)

namespace app\index\controller;

 

use think\Controller;

use app\index\model\User;//使用咱们刚刚新建的那个模型

//use think\Loader;//经过引入think下的Loader类

class Index extends Controller

{

    public function index()

    {

        $userModel = new User;

        //那么此时,咱们就能够对数据库进行添加的操做了

        $userModel->username = 'shulv3';

        $userModel->password = md5('shulv3');

        $userModel->email = 'shulv3@qq.com';

        $userModel->num = 103;

 

        $userModel->save();

 

        dump($userModel->id);

    }

}

  •  

 

固然咱们还可使用一种简单的方法,就是直接给save()传递一个数组,数组的元素为插入的值,就像create()方法传递参数那样。不同的地方是,但碰见插入的字段,表中不存在的时候,它的处理方法是调用一个allowField()方法

$userModel = new User;

        $res = $userModel

        ->allowField(true)

        ->save([//allowField('true')也能够传递一个数组,元素为容许插入的字段名

            'username' => 'shulv4',

            'password' => md5('shulv5'),

            'email'    => 'shulv@qq.com',

            'demo'     => 123

        ]);//返回值是插入的条数

 

        dump($res);

  •  

 

那么当咱们想要添加多条记录时,咱们可使用saveAll()方法,参数为一个二维数组

public function index()

    {

        $userModel = new User;

        $res = $userModel->saveAll([

            ['email' => 'shulv4@qq.com'],

            ['email' => 'shulv5@qq.com']

        ]);//我这里只插入了email

 

        foreach($res as $value){

            dump($value->id);

            //dump($value->toArray());

        }

    }

  •  
  •  

1、使用模型更新数据 

若是咱们想更新数据,咱们在前边说Db类的时候咱们知道,咱们须要一些where条件,我直接用代码演示:

public function index()

    {

       $res = User::update([//经过Model的update()方法,传递一个数组进行数据更新

            'username'  => '3404767031'

       ], ['id'=>80]);//表示更新id=80的这条记录的username

       dump($res);

    }

第二个参数,还能够支持一个闭包函数,和以前说的同样:

 public function index()

    {

       $res = User::update([//经过Model的update()方法,传递一个数组进行数据更新

            'username'  => 'test'

       ], function($query){

            $query->where("id", "<", 85);

       });//表示更新id<85的这几条记录的username

       dump($res);

       //固然能够直接经过咱们以前说的那种,链式操做的方式来构造where条件:User::where()->update();

  •  

 

其实,咱们还有一种更新数据的方法,那就是,现获取到某条记录,而后再对记录中的字段进行修改:

$userModel = User::get(80);

        $userModel->username = 'shulv_80';

        $res = $userModel->save();

       dump($res);

  •  

咱们还能够经过saveAll()的方法进行批量更新数据

$userModel = new User;

        $res = $userModel->saveAll([

            ['id'=>88, 'username' => 'hhhhhh'],

            ['id'=>89, 'username' => 'tttttt']

        ]);

       dump($res);

  •  

2、使用模型删除数据

//Model类为咱们提供了destory()静态方法来删除数据

        $res = User::destroy(79);//若是表中存在主键,咱们能够直接传递主键进行删除 

        dump($res); 

  •  

 

//Model类为咱们提供了destory()静态方法来删除数据

        // $res = User::destroy(79);//若是表中存在主键,咱们能够直接传递主键进行删除 

        // dump($res);  

        $res = User::destroy(['id'=>80]);//也能够经过传递数组的方式

 

        $res = User::destroy(function($query){

            $query->where("id", "<", 85);

        });//还能够经过闭包函数的方式

 

        //经过先获取到执行的记录,而后进行删除

        $userModel = User::get(90);

        $res = $userModel->delete();

 

        //添加where条件进行删除

        $res = User::where("id", "=", 91)->delete();//返回值是删除的记录数

        //删除全部数据  $res = User::where("1=1")->delete();

        dump($res);

  •  

3、模型聚合操做 

在thinkphp的model中为咱们提供了很方便获取平均值、最大值、最小值、数据条数的方法。下边就用代码演示这些函数的用法:

 $res1 = User::count();//获取总记录数

        dump($res1);

        $res2 = User::where("id", ">", 90)//获取id>90的记录数

             ->count();

        dump($res2);

 

        $res3 = User::max('num');//获取num字段中的最大值

        dump($res3);

 

        $res4 = User::where("id", ">", 90)//获取id>90的记录中num值最大的那个记录

             ->max('num');

        dump($res4);

 

        //其他的还有sum(),avg()等方法的使用都是这样,就不一一写了

  •  

 

4、模型获取器 

在咱们的实际应用中,咱们常常会存在这样的场景,好比说咱们存用户的性别,咱们可能在数据库中只使用0,1,20或1,2,3的方式来存用户的性别。0:男1:女2:未知。咱们在数据库中存的是0,1,2而咱们在页面中展现的是男女和未知,那么在获取这个数据的过程当中,咱们就使用获取器,能够自动的将咱们的数据转化成咱们想要的显示格式

app/index/model/User.php

<?php

namespace app\index\model;

use think\Model;

 

class User extends Model{

    public function getSexAttr($val){//注意这个方法名的写法是固定的

        //dump($val);//咱们在这里先直接打印这个$val,能够看到输出的是int(0),也就是说咱们能直接获取到咱们当前获取的数据的value值,那么咱们就能够对其进行判断

        switch ($val) {

            case '1':

                return "男";

                break;

            case '2':

                return "女";

                break;

            default:

                return "未知";

                break;

        }

    }//写完这个函数以后,刚才输出的0,如今就会输出  未知

  •  

app/index/controller/Index.php

 

<?php

namespace app\index\controller;

 

use think\Controller;

use app\index\model\User;//使用咱们刚刚新建的那个模型

//use think\Loader;//经过引入think下的Loader类

class Index extends Controller

{

    public function index()

    {

       //首先咱们先看一下怎么常规的获取到一条记录的sex字段值

       $res = User::get(80);

       echo $res->sex;

       //那么如今咱们若是想让0:未知 1:男 2:女    那么这个时候咱们须要在模型中编写一个函数

 

       dump($res->toArray());//此时会打印出id=80的这条记录,咱们会发现sex显示的是 未知

       //那么,若是咱们想获取到原始数据,可使用getData()

       dump($res->getData());

    }

  •  

1、模型修改器+自动完成 

将这两个放在一块儿学习,是由于这两个有不少的类似之处,下边看一下修改器

控制器Index.php

public function index()

    {

       //首先咱们向数据库中添加一条数据

        $res = User::create([

            'username'  => 'liangyu',

            'password'  => 'liangyu',//注意,我这里没有对其加密,后边我会让它自动完成修改,也就是要说的修改器

            'email'     => 'liangyu@qq.com',

            'num'       => 520

        ]);

        dump($res->id);

    //密码没有加密,那么咱们如何经过修改器让它进行自动的修改,这个时候就须要在模型中编写代码

    }

  •  

模型User.php

public function setPasswordAttr($val){

        return md5($val);//定义了这个方法以后,它会自动传递password给$val

    //这个时候,当咱们再进行数据插入的时候,它就会对密码自动的进行加密

    }

    //固然咱们还能够传递第二个参数$data,它接收的是,咱们插入的这条数据的全部元素(以前说的那个自动将0在输出的时候打印为“未知”,那个getSexAttr的方法,也能够传递第二个参数$data,表示的含义是同样的)

    public function setPasswordAttr($val, $data){

        return $val . $data['email'];//这个就表示,将密码+email总体当作最终密码,固然还能够对总体进行加密,这样更安全

        //return md5($val . $data['email']);

    }

  •  

 

而后咱们说一下自动完成:

控制器Index.php

 public function index()

    {

       //首先咱们向数据库中添加一条数据

        $res = User::create([

            'username'  => 'liangyu',

            'password'  => 'liangyu',

            'email'     => 'liangyu@qq.com',

            'num'       => 520

        ]);

        dump($res->id);

    }

  •  

模型User.php

//若是想使用自动完成,那么就须要在模型中声明

    protected $auto = [//数组中的内容,就是咱们要自动的字段

        'time'

    ];//这个$auto是在咱们进行数据添加和更新的时候都会发生变化,都会发生的操做。它的方法和咱们的修改器是同样的

    public function setTimeAttr(){//首先,咱们修改一下本身的数据库,在咱们的数据库中添加一个time字段

        return time();

    }//这个时候,刷新数据库,新添加的这条数据就有了time()

  •  

 

控制器:Index.php

public function index()

    {

       //首先咱们向数据库中添加一条数据

        $res = User::create([

            'username'  => 'liangyu',

            'password'  => 'liangyu',

            'email'     => 'liangyu@qq.com',

            'num'       => 520

        ]);

        // $userModel = new User;

        // $userModel->get(101);

        // $userModel->sex = 1;

        // $res = $userModel->save(); 

        dump($res->id);

    }

  •  

模型User.php

namespace app\index\model;

use think\Model;

 

class User extends Model{

//若是想使用自动完成,那么就须要在模型中声明

    protected $auto = [//数组中的内容,就是咱们要自动的字段

        'time'

    ];//这个$auto是在咱们进行数据添加和更新的时候都会发生变化,都会发生的操做。它的方法和咱们的修改器是同样的

 

//另外,咱们还能够声明一个$insert数组,这个数组,它只在数据插入的时候有效

    protected $insert = [

        'time_insert'

    ];

    //一样咱们还能够添加$update数组,它是在数据更新的时候发生改变

    $protected $update = [//咱们在数据库中首先使用以前学过的修改记录的值,进行修改,那么该修改器会被自动调用

        'time_update'

    ];

    public function setTimeAttr(){//首先,咱们修改一下本身的数据库,在咱们的数据库中添加一个time字段

        return time();

    }//这个时候,刷新数据库,新添加的这条数据就有了time()

    public function setTimeInsertAttr(){//这个时候,咱们先去给咱们的数据表添加一个time_insert字段

        return time();//插入时间

    }//这样咱们再刷新一下咱们的页面,机会看见数据表中新添的记录中有了time_insert值

    public function setTimeUpdateAttr(){

        return time();

    }

    //这种修改器函数的命名是set+字段名(驼峰命名法)+Attr()

}

  •  

2、模型时间戳+软删除 

时间戳是作什么使用的呢? 

好比说咱们对数据进行新增或更新的操做时,咱们每每须要在数据库中记录咱们的插入时间和更改时间。经过前边的知识咱们知道,咱们可使用自动完成的方式来实现这个功能,可是,咱们大多数的数据库会有这样的字段,若是咱们每个都要这样去编写这样自动更新或自动完成的操做,那么咱们的代码就会变得很臃肿,咱们实现起来也不是很方便。因此thinkphp的model类,为咱们提供了自动的时间戳功能,它会将咱们数据的更新时间和建立时间记录到数据库中。 

软删除 

在咱们对数据进行删除的操做,咱们每每不会将这条数据真正的从数据库中删除,而是将它的某一个字段设置为一个特定的值,表明这个字段已经被删除,或者表明这条记录已经被删除。下边用代码演示一下:

首先我会将以前的那个表删除掉,从新建立一个表,由于以前的表字段太多,模拟起来不方便(表名不变) 

表结构 

 

控制器:Index.php

namespace app\index\controller;

 

use think\Controller;

use app\index\model\User;//使用咱们刚刚新建的那个模型

//use think\Loader;//经过引入think下的Loader类

class Index extends Controller

{

    public function index()

    {

//第一种方式

//若是咱们想全局的开启添加时间和更新时间,时间戳的自动完成这个操做,那么咱们能够修改配置文件(database.php中找到auto_timestamp,将它的值设置为true)

    //而后咱们如今开始插入数据

        $res = User::create([

            'name'     =>  'shulv',

            'password' =>  md5('liangyu')

        ]);

        dump($res);//当咱们刷新页面的时候就会发现,create_time和update_time字段已经有值了

    //可是,并非全部的表都有新增时间和更新时间的字段,因此通常状况下不建议直接在配置文件中进行修改。由于它若是修改的话,若是你的一个表中不存在时间戳的字段,那么程序可能就会报错,因此咱们仍是将它设置为false

 

    //这个时候咱们进入对应的模型(User.php)中添加一个属性$autoWriteTimestamp

 

//咱们再进行一下修改的操做

        $user = User::get(0);

        $user->name = 'liangyu';

        $res = $user->save();

        dump($res);//此时咱们会发现数据库中id=0的这条记录的两个时间戳字段的值也发生了更新

 

/*

如今有一个问题就是,若是咱们数据库中的两个时间戳字段名不是create_time和update_time,好比说我给它们改为create_at和update_at,那么此时咱们再刷新的时候,他就会报错,说update_time和update_time不存在。由于咱们在使用配置的时候,它的默认配置就是update_time,因此咱们须要在model中继续申请一个属性

*/

    }

}

  •  

模型:User.php

namespace app\index\model;

use think\Model;

 

class User extends Model{

    protected $autoWriteTimestamp = true;//利用这个属性来开启时间戳功能。这个时候咱们再更新页面,那两个时间戳字段也会被添加进去

    protected $createTime = 'create_at';//这里直接写上咱们的字段名

    protected $updateTime = 'update_at';//这个时候咱们再刷新浏览器就不会报错了,时间也会被更新

//固然咱们还能够将$createTime或$updateTime设置为false,即是关闭该项,那么它会使用默认值(0),就不会去更新这个字段了

}

  •  

软删除

控制器:Index.php

namespace app\index\controller;

 

use think\Controller;

use app\index\model\User;//使用咱们刚刚新建的那个模型

//use think\Loader;//经过引入think下的Loader类

class Index extends Controller

{

    public function index()

    {

//在说软删除的时候,咱们先向数据库中添加一个delete_time字段(容许为null,null表明这条数据没有被删除)

//若是咱们想使用软删除,咱们须要在模型中引入traits\modelSoftDelete(去看模型User.php)

        //在模型中引入traits\modelSoftDelete以后,就能够直接在控制器中进行删除了

        $res = User::destroy(0);

        dump($res);

//这个时候咱们在数据表中能够看见id=0的字段并无被真正的删除,它的delete_time字段名变成了时间戳,说明这条数据在指定的时间点被删除(软删除)。这个时候当你尝试获取刚刚被软删除的记录时,返回的是null,也就是说不能再获取了。若是你确实须要获取到咱们包含软删除的这些记录,那么咱们就可使用下边这样的方式

        $res = User::withTrashed(true)->find(0);//这个时候就能获得了

        dump($res);

        dump($res->getData());//能够获取原始数据

 

//还有一种方式就是,好比说咱们软删除的记录都放在了垃圾箱里,那么咱们要获取这些被软删除的数据,就能够这样

        $res = User::onlyTrashed()->select();//返回的是数组,咱们能够经过foreach遍历

        dump($res);

//那么,若是咱们想对数据进行恢复,能够直接使用update方法,将delete_time的值设置为null便可

//当咱们不想软删除这个字段名为delete_time时,咱们仍是使用更改create_time那种在model中声明变量的方式进行更改

 

//那么若是咱们真正的想删除某一个记录时应该怎么作呢?

        $res = User::destroy(0, true);//传递第二个参数为true便可

        dump($res);

//还能够经过先获取,再删除的方式

        $user = User::get(0);

        $res = $user->delete(0, true);

        dump($res);

    }

}

  •  

模型:User.php

 

namespace app\index\model;

use think\Model;

use traits\modelSoftDelete;

class User extends Model{

 

    use SoftDelete;

    protected $autoWriteTimestamp = true;//利用这个属性来开启时间戳功能。这个时候咱们再更新页面,那两个时间戳字段也会被添加进去

    protected $createTime = 'create_at';//这里直接写上咱们的字段名

    protected $updateTime = 'update_at';//这个时候咱们再刷新浏览器就不会报错了,时间也会被更新

//固然咱们还能够将$createTime或$updateTime设置为false,即是关闭该项,那么它会使用默认值(0),就不会去更新这个字段了

    protected $updateTime = 'delete_at';

}

相关文章
相关标签/搜索