SoftDelete.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. // 传入空不执行删除,但是0可以删除
  118. if (empty($data) && 0 !== $data) {
  119. return false;
  120. }
  121. // 包含软删除数据
  122. $query = (new static())->db(false);
  123. if (is_array($data) && key($data) !== 0) {
  124. $query->where($data);
  125. $data = null;
  126. } elseif ($data instanceof \Closure) {
  127. call_user_func_array($data, [ & $query]);
  128. $data = null;
  129. } elseif (is_null($data)) {
  130. return false;
  131. }
  132. $resultSet = $query->select($data);
  133. if ($resultSet) {
  134. foreach ($resultSet as $data) {
  135. $data->force($force)->delete();
  136. }
  137. }
  138. return true;
  139. }
  140. /**
  141. * 恢复被软删除的记录
  142. * @access public
  143. * @param array $where 更新条件
  144. * @return bool
  145. */
  146. public function restore($where = [])
  147. {
  148. $name = $this->getDeleteTimeField();
  149. if ($name) {
  150. if (false === $this->trigger('before_restore')) {
  151. return false;
  152. }
  153. if (empty($where)) {
  154. $pk = $this->getPk();
  155. $where[] = [$pk, '=', $this->getData($pk)];
  156. }
  157. // 恢复删除
  158. $this->db(false)
  159. ->where($where)
  160. ->useSoftDelete($name, $this->getWithTrashedExp())
  161. ->update([$name => $this->defaultSoftDelete]);
  162. $this->trigger('after_restore');
  163. return true;
  164. }
  165. return false;
  166. }
  167. /**
  168. * 获取软删除字段
  169. * @access protected
  170. * @param bool $read 是否查询操作 写操作的时候会自动去掉表别名
  171. * @return string|false
  172. */
  173. protected function getDeleteTimeField($read = false)
  174. {
  175. $field = property_exists($this, 'deleteTime') && isset($this->deleteTime) ? $this->deleteTime : 'delete_time';
  176. if (false === $field) {
  177. return false;
  178. }
  179. if (false === strpos($field, '.')) {
  180. $field = '__TABLE__.' . $field;
  181. }
  182. if (!$read && strpos($field, '.')) {
  183. $array = explode('.', $field);
  184. $field = array_pop($array);
  185. }
  186. return $field;
  187. }
  188. /**
  189. * 查询的时候默认排除软删除数据
  190. * @access protected
  191. * @param Query $query
  192. * @return void
  193. */
  194. protected function withNoTrashed($query)
  195. {
  196. $field = $this->getDeleteTimeField(true);
  197. if ($field) {
  198. $condition = is_null($this->defaultSoftDelete) ? ['null', ''] : ['=', $this->defaultSoftDelete];
  199. $query->useSoftDelete($field, $condition);
  200. }
  201. }
  202. }