首頁 >後端開發 >php教程 >TP5 Model 功能總結

TP5 Model 功能總結

*文
*文原創
2017-12-21 14:00:484781瀏覽

TP5提供了強大的Model功能,跟著這篇文章來一探究竟。

簡介

  1. tp5的model只做業務層操作,不做特定的連結資料庫sql操作。

  2. think\db\Connection.php做連結資料庫操作

  3. #think\db\Builder.php做建立sql操作

  4. think\db\Query.php做資料CURD作業

#功能清單

  1. # #資料自動完成

  2. 自動寫入時間戳

  3. #時間欄位自動格式化輸出欄位

  4. 字段驗證器

  5. 自動關聯寫入

  6. #只讀字段

  7. ## 隱藏字段
  8. 事件回呼
  9. 軟刪除
  10. 類型轉換
  11. #功能詳情

1. 資料自動完成

   //设置自动完成的字段,支持键值对数组和索引数组
    //新增和更新时都会使用
    //如:['name'=>'zhangsan','sex'=>'男']
    // ['name','sex']
    protected $auto = [];    //新增 自动完成列表
    //只在新增数据的时候使用
    protected $insert = [];    //更新 自动完成列表
    //只在更新数据的时候使用
    protected $update = [];    //用来标记当前操作被修改的字段
    //如 ['name','sex']
    protected $change = [];    //依赖方法,model类会自动调用解析auto数组
    //我们只需配置auto数组即可
    protected function autoCompleteData($auto = []){}

在model中設定完auto欄位後在更新或新增的時候首先會判斷auto中設定的欄位是否存在於被更新的欄位($this->change)中

如果存在則不用auto裡設定的欄位和值

如果不存在則將auto裡設定的欄位和值加到this−>data中並把該欄位加入this->change中。

如果auto是索引數組,也就是只設定了字段名,沒有設定子字段值,這是就會根據字段名去$this->data中查詢該字段值,並添加的到要更新的屬性數組中去。

新增資料的方法是create, 修改資料的方法是update,批次新增和修改的方法是saveAll,這幾個方法的最終實作都是呼叫的save方法

saveAll方法批次新增和修改,不是組合sql語句,而是開啟事務,然後呼叫save方法,一一新增和修改,最後提交事務。

在更新操作中,model會自動檢查data的所有欄位的值是否被更改,只會跟著新被更改過得欄位的值。沒被更改的則被忽略。

insert、update的功能和auto的功能類似,只不過auto是不管是新增資料和是更新資料都會使用,而insert值針對新增,update只針對更新。如果設定了相同的屬性,insert和update的則會覆蓋auto中的欄位。

2. 自動寫入時間戳

   //是否需要自动写入时间戳
    //可以是字符串类型和boolean类型
    //字符串类型代表要写入的时间格式
    //如: 'Y-m-d H:i:s'
    //boolean类型就是true和false,代表是否开启
    //默认时间格式为int类型
    protected $autoWriteTimestamp;    //默认自动写入的字段有
    //创建时间和更新时间,他们对应的字段名分别是
    //create_time,和update_time
    //也可以在model里自己设置。
    protected $createTime = 'create_time';    protected $updateTime = 'update_time';

配置方式

該配置TP5預設為false,需要手動開啟

在資料庫配置(database. php)中新增全域配置。

   'auto_timestamp' => true
    //或者设置时间格式
    // 'auto_timestamp' => 'datatime'

在單獨的模型類別裡設定

   protected $autoWriteTimestamp = true;    //或者设置时间格式
    // protected $autoWriteTimestamp = 'datatime';

知識的欄位類型timestamp/datetime/int

如果自己的資料欄位不是預設值得話,可以在自己的model裡修改。

   //如:
    protected $createTime = 'my_create_time_filed';    
    protected $updateTime = 'my_careate_time_field';

如果只需要createTime而不需要updateTIme,則可以在model中關閉updateTIme

   //如
    protected $updateTime = false;123

在model中開啟和關閉只針對單獨的model起作用,想要全域起作用還是要在設定檔裡配置。

3.時間欄位自動格式化輸出

   //输出格式
    protected $dateFormat;123

設定方式

該設定TP5模式輸出格式為'Y-m-d H:i:s'

#可以自己在資料庫設定檔(database.php)中設定。如

   'datetime_format' => 'Y/m/d H:i',12

也可以在model中設定

   protected $dateFormat = 'Y/m/d H:i';12

4. 欄位驗證器

   //字段验证规则
    protected $validate = [];    //是否采用批量验证
    protected $batchValidate = false;    /**
     * 设置字段验证
     * @access public
     * @param array|string|bool $rule  验证规则 true表示自动读取验证器类
     * @param array             $msg   提示信息
     * @param bool              $batch 批量验证
     * @return $this
     */
    public function validate($rule = ture,$msg=[],$bath=false){}    /**
     * 自动验证数据
     * @access protected
     * @param array $data  验证数据
     * @param mixed $rule  验证规则
     * @param bool  $batch 批量验证
     * @return bool
     */
    public function validateData($data,$rule=null,$batch=null){}

使用方式

在model中設定欄位驗證規則,在整個model新增和更新操作都通用。

   // 優點:只需設定一次,即可通用

   // 缺點:無法針對化設定

   //例如:新增使用者和編輯使用者功能,
   //新增是密碼為必填項,編輯時密碼就是選填項了
   //所以就不能再model裡設定密碼的驗證規則了,
   這個時候就只能在新增的action裡為密碼做驗證了。

protected $validate = [        
        'rule' => [            
                'name' => 'require',            
                //多个规则可以是用字符串用|分隔
           //也可以使用数组['require','number','min'=>10,'max'=>80]
           //使用字符串配置要被使用explode('|',$rule)转化成数组,所以使用数组配置效率更高
           'age' => 'require|number|min:10|max:80',            
           'height' => 'between:100,200'
        ],        
       'msg' => [            
             'name' => 'name不能为空',            
             'age.require' => 'age不能没空',            
             'age.number' => 'age必须是一个数字',            
             'age.min' => 'age最小为10',            
             'age.max' => 'age最大为80',            
             'height' => 'height只能在100到200之间'
        ]
    ];

在具體操作時呼叫think\Validate類別來實作

   //在类的头部,因为Validate文件。
    use think\Validate;    
    $validate = new Validate([     
       'name' => 'require',    
       'age' => 'require|number|min:10|max:80'
    ],[        
          'name' => 'name不能为空',        
          'age.require' => 'age不能没空',        
          'age.number' => 'age必须是一个数字',        
          'age.min' => 'age最小为10',        
          'age.max' => 'age最大为80',
    ]);    
    //使用check检查数据
    if($validate->check($data)){     
       echo '数据格式符合要求';
    }else{      
          //比如:name不能为空
        echo $validate->getError();
    }

對比

使用第一種方法在model裡設定驗證規則,雖然說結構看著比較合理,但是這種方法靈活性比較低,因為他是在save的時候去判斷的,如​​果save失敗,你不清楚是資料驗證失敗,還是說插入到資料失敗。所以對於做提示驗證很麻煩(因為資料驗證的提示我們是直接回傳給使用者的,而資料庫操作的提示一般我們是不回傳給使用者的,所以得到結果後還要做判斷,先對比較麻煩)。

使用第二种方法在action里定义一个_validate的函数,专门用来做数据校验,这中方法比较灵活,而且他是在在保存数据之前做的校验,所以返回结果分的比较清楚,对用户的提示也比较清晰,代码可读性也比较好。

5. 自动关联写入

   // 关联对象
    protected $relation;    // 关联自动写入(关联的属性名)
    protectd $relationWrite = [];

暂时没有使用,后续再继续不补充。

6. 只读字段

   //用来保护那些不许要被更新的字段。
    //比如,创建时间
    //设置后再更新数据时,会字段过滤掉create_time字段
    //避免更新到数据库。
    protected $readonly = ['create_time'];

7. 隐藏字段

    //设置要隐藏的字段,
    //该设置只在toArray(),和subToArray()方法中起作用
    protected $hidden = [];    //相关方法
    public function hidden($hidden=[],$override=false){
    }

当使用toArray和subToArray获得数组数据时,使用hidden字段和hidden函数可以隐藏数组中的元素。如:

    //user表的属性字段(模拟操作)
    user_field = ['name','sex','age','height'];

   在User模型中设置$hidden字段    

   protected $hidden = ['age','height'];
    dump($User->toArray()); //只有name和sex字段。
    //也可以调用hidden方法隐藏字段
    //会有 name,age,height 三个字段
    dump($User->hidde(['sex'])->toArray()); 
    //只有name字段了
    //第二个参数标识是否合并 $this->hidden 
    dump($user->hidden(['sex'],true)->toArray());

8. 事件回调

支持的回调事件

before_insert 新增前

after_insert 新增后

before_update 更新前

after_update 更新后

before_write 写入前(新增和更新都会调用)

after_write 写入后(新增和更新都会调用)

before_delete 删除前

after_delete 删除后

注册的回调方法支持传入一个参数,当前示例模型对象,并且before_write,before_insert,before_update,before_delete返回false会结束执行。

使用方法

控制器里使用

   //支持给一个位置注册多个事件    
   User::event('before_insert',function($user){        
       if($user->status != 1){            
           return false;        
       }    
   });    
    //这个也会生效,回到函数为beforeInsert    
  User::event('before_insert','beforeInsert');

模型里使用

   //使用init方法统一注册模型事件
    class User extends Model{
        protected static function init(){
            User::event('before_insert',function($user){
                if($user->status != 1){                    
                    return false;
                }
            }            
            //注册第二个事件
            User::event('before_insert','beforeInsert');
        }
    }

原理

model类里有一个protected static $event = [];属性,注册的时间都存放在这个属性中。比如:

   $event = [        
          //模型名称
        'user' => [            
              //事件名称
            'before_insert' => ['callback_funciton','beforeInsert'],            
            'after_insert' => ['callback_function','afterInsert'],            
            'before_delete' => ['beforeDelete']
        ]
    ]

注册事件时,把所有的事件都保存在$event中了,然后在insert,update,delete等相应的位置调用即可。

9. 软删除

简介

在实际项目中,对数据频繁的使用删除操作可能会导致性能问题,软删除的作用就是给数据加上删除标记,而不是真正的删除,同时也便于需要的时候恢复数据。

设置方式

使用软删除功能需要引用SoftDelete trait;如:

   namespace app\index\model;    
   use think\Model;    
   use think\model\SoftDelete;    
   class User extends Model{
        // 使用SoftDelete
        // trait 的使用方式
        // 使用trait跟类的继承相似
        use SoftDelete;        
        //软删除标记的字段名
        protected $deleteTime = 'delete_time';
    }

dateteTIme属性用于标记数据表里的软删除字段,TP5里的软删除使用的是int类型,默认值为null(这个很重要,因为查询的时候是用delete_time is not null 来查询的),用于记录删除时间。

可以用类型转换指定软删除的字段类型,建议数据表里的所有时间字段使用同一种数据类型。

使用方式

在model中设置好后,就可以直接使用了

   //软删除
    User::destory(1);    
    //真删除
    User::destory(1,true);    
    //软删除
    $user = User::get(1);    
    $user->delete();    
    //真删除
    $user->delete(true);

默认情况下,查询出来的数据是不包括软删除的数据的,如果想要查询包括软删除的数据,可以使用下面的方式。

    User::withTrashed()->find();
   User::withTrashed()->select();

如果仅需要查询软删除的数据,可以这样:

    User::onlyTranshed()->find();
   User::onlyTranshed()->select();

10. 类型转换

TP5支持给数据表中的字段设置类型,并会在读取和写入的时候自动转换。如:

   class User extends Model{
        protected $type = [            
            'status' => 'integer',            
            'score' => 'float',            
            'login_timme' => 'datetime',            
            'info' => 'array'
        ];
    }

使用示例

   $user = new User;    
    $user->status = '1';    
    $user->score = '90.50';    
    $user->birthday = '2015/5/1';    
    $user->info = ['a'=>1,'b'=>2];    
    $user->save();
    var_dump($user->status); // int 1
    var_dump($user->score); // float 90.5;
    var_dump($user->birthday); // string '2015-05-01 00:00:00'
    var_dump($user->info);// array (size=2) 'a' => int 1  'b' => int 2

注意: 如果制定为时间戳类型(timestamp)的话,该字段会在写入的时候自动调用strtotime函数生成对应的时间戳,输出是自动使用dateFormat格式化时间戳,默认格式为Y:m:d H:i:s,如果想要改变输出格式,可以如下:

   class User extends Model{
        protected $dataFormat = 'Y/m/d';        
        protected $type = [            
            'status' => 'integer',            
            'score' => 'float',            
            'birthday' => 'timestemp'//时间戳格式
        ];
    }

或者如下:

   class User extends Model{        
       protected $type = [            
           'status' => 'integer',            
           'socre' => 'float',            
           'birthday' => 'timestemp:Y/m/d'//写入时间戳,读取按照Y/m/d的格式来格式化输出。        
       ]; 
      }

  

相关阅读:

最详细的ThinkPHP5自定义分页类教程

thinkphp执行原生SQL语句的实现方法.

thinkphp5实现分页功能的方法介绍


以上是TP5 Model 功能總結的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn