## 軟刪除:SoftDelete
>[info] 軟刪除其實就是:偽刪除,沒有真正的刪除。正所謂,吃軟飯的都是偽男一樣的。
軟刪除是相對于硬刪除來說的,所謂“軟”是指刪除以后,還可以恢復的。而“硬刪除”則是物理刪除,是真正的將數據從硬盤上擦掉了。
* * * * *
#### 1. 步驟:總的來說就二步
1. 在對應的模型類中做好相關的設置工作;
2. 在控制器中對該模型進行調用。
* * * * *
#### 2. 源碼:/thinkphp/library/traits/model/SoftDelete.php
>[info] 源碼中注釋是本人單獨添加,官方源碼中并無這么多的注釋
~~~
<?php
namespace traits\model;
trait SoftDelete
{
/**
* 判斷當前實例是否被軟刪除
* @access public
* @return boolean
*/
public function trashed()
{
//獲取軟刪除字段名稱
$field = $this->getDeleteTimeField();
//如果當前數據對象的軟刪除字段為null,則已軟刪除
if (!empty($this->data[$field])) {
return true;
}
//否則返回false,表示沒有被軟刪除
return false;
}
/**
* 查詢軟刪除數據
* @access public
* @return \think\db\Query
*/
public static function withTrashed()
{
//實例化靜態調用該方法的類,通常是子類:自定義的模型類,如Staff,User
$model = new static();
//getDeleteTimeField(true)表示當前為讀操作:false表示寫操作
$field = $model->getDeleteTimeField(true);
//在查結結果中,去掉已軟刪除的記錄
return $model->db(false)->removeWhereField($field);
}
/**
* 只查詢軟刪除數據
* @access public
* @return \think\db\Query
*/
public static function onlyTrashed()
{
//實例化靜態調用該方法的類
$model = new static();
//獲取軟刪除字段(true為讀操作)
$field = $model->getDeleteTimeField(true);
//只輸出刪除字段不為空的數據,其實就是已經軟刪除的記錄:理論上已刪除
return $model->db(false)->where($field, 'exp', 'is not null');
}
/**
* 刪除當前的記錄
* 此方法會覆蓋父類Model類中的delete方法,就是trait類的用處:多繼承
* @access public
* @param bool $force 是否強制刪除 true:硬刪除
* @return integer
*/
public function delete($force = false)
{
if (false === $this->trigger('before_delete', $this)) {
return false;
}
$name = $this->getDeleteTimeField();
if (!$force) {
// 軟刪除
$this->change[] = $name;
$this->data[$name] = $this->autoWriteTimestamp($name);
$result = $this->isUpdate()->save();
} else {
$result = $this->db()->delete($this->data);
}
$this->trigger('after_delete', $this);
return $result;
}
/**
* 刪除記錄/軟刪除
* 該方法同樣覆蓋父類Model同名方法,用于靜態調用
* @access public
* @param mixed $data 主鍵列表 支持閉包查詢條件
* @param bool $force 是否強制刪除
* @return integer 成功刪除的記錄數
*/
public static function destroy($data, $force = false)
{
//實例化當前調用類
$model = new static();
$query = $model->db();
if (is_array($data) && key($data) !== 0) {
$query->where($data);
$data = null;
} elseif ($data instanceof \Closure) {
call_user_func_array($data, [ & $query]);
$data = null;
} elseif (is_null($data)) {
return 0;
}
$resultSet = $query->select($data);
$count = 0;
if ($resultSet) {
foreach ($resultSet as $data) {
$result = $data->delete($force);
$count += $result;
}
}
return $count;
}
/**
* 恢復被軟刪除的記錄
* @access public
* @param array $where 更新條件
* 參數為空,則恢復全部被軟刪除的數據
* @return integer
*/
public function restore($where = [])
{
$name = $this->getDeleteTimeField();
// 恢復刪除
return $this->isUpdate()->save([$name => null], $where);
}
/**
* 查詢默認不包含軟刪除數據
* @access protected
* @param \think\db\Query $query 查詢對象
* @return void
*/
protected function base($query)
{
$field = $this->getDeleteTimeField(true);
$query->where($field, 'null');
}
/**
* 獲取軟刪除字段
* @access public
* @param bool $read 是否查詢操作 寫操作的時候會自動去掉表別名
* @return string
*/
protected function getDeleteTimeField($read = false)
{
//獲取軟刪除字段名稱,如用戶沒有自定義,則設置成默認值:delete_time
$field = isset($this->deleteTime) ? $this->deleteTime : 'delete_time';
//判斷字段名如果存在'.',則獲取表名,并添加到字段前
if (!strpos($field, '.')) {
$field = $this->db(false)->getTable() . '.' . $field;
}
//寫操作時,去掉表名
if (!$read && strpos($field, '.')) {
$array = explode('.', $field);
$field = array_pop($array);
}
//返回軟刪除字段名稱
return $field;
}
}
~~~
>[warning] 閱讀源碼,發現有很多有用的方法,可以供模型類調用!其中的delete和destroy方法,直接攔截了調用Model類的對應方法,實現了軟刪除,理解這點很重要,這也是trait類的作用之一。
* * * * *
#### 3. 方法總結:
* 普通方法(public function )
| 序號 | 名稱 | 參數 | 返回值 | 功能 |
| --- | --- | --- | --- | --- |
| 1 | trashed | 無 | 布爾值 | 判斷當前實例是否被軟刪除 |
| 2 | delete | 布爾值 | 刪除數量 | 刪除當前的數據對象 |
| 3 | restore | 條件表達式 | 恢復數量 | 恢復被軟刪除的記錄 |
* 靜態方法(public static)
| 序號 | 名稱 | 參數 | 返回值 | 功能 |
| --- | --- | --- | --- | --- |
| 1 | withTrashed | 無 | Query對象 | 查詢軟刪除數據 |
| 2 | onlyTrashed | 無 | Query對象 | 只查詢軟刪除數據 |
| 3 | destroy | 主鍵/表達多/閉包 | 刪除數量 | 刪除數據 |
* 保護方法(protected function)
| 序號 | 名稱 | 參數 | 返回值 | 功能 |
| --- | --- | --- | --- | --- |
| 1 | base | Query對象 | 無定義 | 查詢默認不包含軟刪除數據 |
| 2 | getDeleteTimeField| 布爾值 | 字段名稱 | 獲取軟刪除字段|
* * * * *
>[success] 下一節,我們以實例來詳細講解幾個常用方法~~
- 前言[隨時更新]
- 開發環境
- 1.Mac環境
- 2.windows環境
- 模型對象
- 1.創建模型對象
- 2.模型初始化
- 數據對象
- 1.定義數據對象
- 2.創建數據對象
- 1.data方法
- 2.setAttr方法
- 3.__set方法
- 4.查詢數據對象
- 1.getData方法
- 2.getAttr方法
- 3.__get方法
- OOP難點總結
- 1.get_class( )實例講解
- 2.get_called_class( )實例講解
- 3.__call( )實例講解
- 3.__callStatic( )實例講解
- 4.call_user_func_array函數[重點]
- 5.普通方法與靜態方法
- 6.在Model源碼中的應用
- 7.new static 延遲靜態綁定
- PHP標準化規范
- 查詢數據
- 1.獲取單條:get靜態方法
- 2.獲取單條:對象查詢
- 3.獲取多條:all靜態方法
- 4.獲取多條:對象查詢
- 5.獲取字段值:value方法
- 6.獲取列值:column方法
- 7.動態查詢:getBy字段名
- 8.助手函數:model查詢
- 9.加載器:Loader類查詢
- 10.數據庫與模型查詢對比
- 新增數據
- 1.sava方法
- 2.savaAll方法
- 3.create靜態方法
- 4.insert靜態調用
- 更新數據
- 1.單條更新:save方法
- 2.批量更新:saveAll方法
- 3.靜態更新:update方法
- 4.查詢類Query直接更新
- 5. 閉包更新
- 刪除數據
- 1.刪除當前記錄:delete
- 2.靜態條件刪除:destory
- 獲取器
- 1.模型方法:set屬性Attr
- 修改器
- 1.set屬性Attr
- 時間戳
- 1.MySQL中日期類型復習
- 2.時間戳功能詳解
- 軟刪除[重點]
- 1.traits詳解[選學內容]
- 2.SoftDelet類源碼分析
- 3. delete實例刪除
- 4.destroy條件刪除
- 5.restore恢復數據
- 類型轉換
- 1. 規則設置
- 2. 實例演示
- 查詢范圍
- 1. 基本概念
- 2.實例演示