SoftDelete.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <?php
  2. namespace think\model\concern;
  3. use think\db\Query;
  4. /**
  5. * 数据软删除
  6. */
  7. trait SoftDelete
  8. {
  9. /**
  10. * 是否包含软删除数据
  11. * @var bool
  12. */
  13. protected $withTrashed = false;
  14. /**
  15. * 判断当前实例是否被软删除
  16. * @access public
  17. * @return boolean
  18. */
  19. public function trashed()
  20. {
  21. $field = $this->getDeleteTimeField();
  22. if ($field && !empty($this->getOrigin($field))) {
  23. return true;
  24. }
  25. return false;
  26. }
  27. /**
  28. * 查询软删除数据
  29. * @access public
  30. * @return Query
  31. */
  32. public static function withTrashed()
  33. {
  34. $model = new static();
  35. return $model->withTrashedData(true)->db(false);
  36. }
  37. /**
  38. * 是否包含软删除数据
  39. * @access protected
  40. * @param bool $withTrashed 是否包含软删除数据
  41. * @return $this
  42. */
  43. protected function withTrashedData($withTrashed)
  44. {
  45. $this->withTrashed = $withTrashed;
  46. return $this;
  47. }
  48. /**
  49. * 只查询软删除数据
  50. * @access public
  51. * @return Query
  52. */
  53. public static function onlyTrashed()
  54. {
  55. $model = new static();
  56. $field = $model->getDeleteTimeField(true);
  57. if ($field) {
  58. return $model
  59. ->db(false)
  60. ->useSoftDelete($field, $model->getWithTrashedExp());
  61. }
  62. return $model->db(false);
  63. }
  64. /**
  65. * 获取软删除数据的查询条件
  66. * @access protected
  67. * @return array
  68. */
  69. protected function getWithTrashedExp()
  70. {
  71. return is_null($this->defaultSoftDelete) ?
  72. ['notnull', ''] : ['<>', $this->defaultSoftDelete];
  73. }
  74. /**
  75. * 删除当前的记录
  76. * @access public
  77. * @return bool
  78. */
  79. public function delete($force = false)
  80. {
  81. if (!$this->isExists() || false === $this->trigger('before_delete', $this)) {
  82. return false;
  83. }
  84. $force = $force ?: $this->isForce();
  85. $name = $this->getDeleteTimeField();
  86. if ($name && !$force) {
  87. // 软删除
  88. $this->data($name, $this->autoWriteTimestamp($name));
  89. $result = $this->isUpdate()->withEvent(false)->save();
  90. $this->withEvent(true);
  91. } else {
  92. // 读取更新条件
  93. $where = $this->getWhere();
  94. // 删除当前模型数据
  95. $result = $this->db(false)
  96. ->where($where)
  97. ->removeOption('soft_delete')
  98. ->delete();
  99. }
  100. // 关联删除
  101. if (!empty($this->relationWrite)) {
  102. $this->autoRelationDelete();
  103. }
  104. $this->trigger('after_delete', $this);
  105. $this->exists(false);
  106. return true;
  107. }
  108. /**
  109. * 删除记录
  110. * @access public
  111. * @param mixed $data 主键列表 支持闭包查询条件
  112. * @param bool $force 是否强制删除
  113. * @return bool
  114. */
  115. public static function destroy($data, $force = false)
  116. {
  117. // 包含软删除数据
  118. $query = (new static())->db(false);
  119. if (is_array($data) && key($data) !== 0) {
  120. $query->where($data);
  121. $data = null;
  122. } elseif ($data instanceof \Closure) {
  123. call_user_func_array($data, [ & $query]);
  124. $data = null;
  125. } elseif (is_null($data)) {
  126. return false;
  127. }
  128. $resultSet = $query->select($data);
  129. if ($resultSet) {
  130. foreach ($resultSet as $data) {
  131. $data->force($force)->delete();
  132. }
  133. }
  134. return true;
  135. }
  136. /**
  137. * 恢复被软删除的记录
  138. * @access public
  139. * @param array $where 更新条件
  140. * @return bool
  141. */
  142. public function restore($where = [])
  143. {
  144. $name = $this->getDeleteTimeField();
  145. if ($name) {
  146. if (false === $this->trigger('before_restore')) {
  147. return false;
  148. }
  149. if (empty($where)) {
  150. $pk = $this->getPk();
  151. $where[] = [$pk, '=', $this->getData($pk)];
  152. }
  153. // 恢复删除
  154. $this->db(false)
  155. ->where($where)
  156. ->useSoftDelete($name, $this->getWithTrashedExp())
  157. ->update([$name => $this->defaultSoftDelete]);
  158. $this->trigger('after_restore');
  159. return true;
  160. }
  161. return false;
  162. }
  163. /**
  164. * 获取软删除字段
  165. * @access protected
  166. * @param bool $read 是否查询操作 写操作的时候会自动去掉表别名
  167. * @return string|false
  168. */
  169. protected function getDeleteTimeField($read = false)
  170. {
  171. $field = property_exists($this, 'deleteTime') && isset($this->deleteTime) ? $this->deleteTime : 'delete_time';
  172. if (false === $field) {
  173. return false;
  174. }
  175. if (false === strpos($field, '.')) {
  176. $field = '__TABLE__.' . $field;
  177. }
  178. if (!$read && strpos($field, '.')) {
  179. $array = explode('.', $field);
  180. $field = array_pop($array);
  181. }
  182. return $field;
  183. }
  184. /**
  185. * 查询的时候默认排除软删除数据
  186. * @access protected
  187. * @param Query $query
  188. * @return void
  189. */
  190. protected function withNoTrashed($query)
  191. {
  192. $field = $this->getDeleteTimeField(true);
  193. if ($field) {
  194. $condition = is_null($this->defaultSoftDelete) ? ['null', ''] : ['=', $this->defaultSoftDelete];
  195. $query->useSoftDelete($field, $condition);
  196. }
  197. }
  198. }