DatabaseRule.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <?php
  2. namespace Illuminate\Validation\Rules;
  3. use Closure;
  4. use Illuminate\Contracts\Support\Arrayable;
  5. use Illuminate\Database\Eloquent\Model;
  6. use Illuminate\Support\Collection;
  7. use function Illuminate\Support\enum_value;
  8. trait DatabaseRule
  9. {
  10. /**
  11. * The table to run the query against.
  12. *
  13. * @var string
  14. */
  15. protected $table;
  16. /**
  17. * The column to check on.
  18. *
  19. * @var string
  20. */
  21. protected $column;
  22. /**
  23. * The extra where clauses for the query.
  24. *
  25. * @var array
  26. */
  27. protected $wheres = [];
  28. /**
  29. * The array of custom query callbacks.
  30. *
  31. * @var array
  32. */
  33. protected $using = [];
  34. /**
  35. * Create a new rule instance.
  36. *
  37. * @param string $table
  38. * @param string $column
  39. */
  40. public function __construct($table, $column = 'NULL')
  41. {
  42. $this->column = $column;
  43. $this->table = $this->resolveTableName($table);
  44. }
  45. /**
  46. * Resolves the name of the table from the given string.
  47. *
  48. * @param string $table
  49. * @return string
  50. */
  51. public function resolveTableName($table)
  52. {
  53. if (! str_contains($table, '\\') || ! class_exists($table)) {
  54. return $table;
  55. }
  56. if (is_subclass_of($table, Model::class)) {
  57. $model = new $table;
  58. if (str_contains($model->getTable(), '.')) {
  59. return $table;
  60. }
  61. return implode('.', array_map(function (string $part) {
  62. return trim($part, '.');
  63. }, array_filter([$model->getConnectionName(), $model->getTable()])));
  64. }
  65. return $table;
  66. }
  67. /**
  68. * Set a "where" constraint on the query.
  69. *
  70. * @param \Closure|string $column
  71. * @param \Illuminate\Contracts\Support\Arrayable|\UnitEnum|\Closure|array|string|int|bool|null $value
  72. * @return $this
  73. */
  74. public function where($column, $value = null)
  75. {
  76. if ($value instanceof Arrayable || is_array($value)) {
  77. return $this->whereIn($column, $value);
  78. }
  79. if ($column instanceof Closure) {
  80. return $this->using($column);
  81. }
  82. if (is_null($value)) {
  83. return $this->whereNull($column);
  84. }
  85. $value = enum_value($value);
  86. $this->wheres[] = compact('column', 'value');
  87. return $this;
  88. }
  89. /**
  90. * Set a "where not" constraint on the query.
  91. *
  92. * @param string $column
  93. * @param \Illuminate\Contracts\Support\Arrayable|\UnitEnum|array|string|int $value
  94. * @return $this
  95. */
  96. public function whereNot($column, $value)
  97. {
  98. if ($value instanceof Arrayable || is_array($value)) {
  99. return $this->whereNotIn($column, $value);
  100. }
  101. $value = enum_value($value);
  102. return $this->where($column, '!'.$value);
  103. }
  104. /**
  105. * Set a "where null" constraint on the query.
  106. *
  107. * @param string $column
  108. * @return $this
  109. */
  110. public function whereNull($column)
  111. {
  112. return $this->where($column, 'NULL');
  113. }
  114. /**
  115. * Set a "where not null" constraint on the query.
  116. *
  117. * @param string $column
  118. * @return $this
  119. */
  120. public function whereNotNull($column)
  121. {
  122. return $this->where($column, 'NOT_NULL');
  123. }
  124. /**
  125. * Set a "where in" constraint on the query.
  126. *
  127. * @param string $column
  128. * @param \Illuminate\Contracts\Support\Arrayable|\BackedEnum|array $values
  129. * @return $this
  130. */
  131. public function whereIn($column, $values)
  132. {
  133. return $this->where(function ($query) use ($column, $values) {
  134. $query->whereIn($column, $values);
  135. });
  136. }
  137. /**
  138. * Set a "where not in" constraint on the query.
  139. *
  140. * @param string $column
  141. * @param \Illuminate\Contracts\Support\Arrayable|\BackedEnum|array $values
  142. * @return $this
  143. */
  144. public function whereNotIn($column, $values)
  145. {
  146. return $this->where(function ($query) use ($column, $values) {
  147. $query->whereNotIn($column, $values);
  148. });
  149. }
  150. /**
  151. * Ignore soft deleted models during the existence check.
  152. *
  153. * @param string $deletedAtColumn
  154. * @return $this
  155. */
  156. public function withoutTrashed($deletedAtColumn = 'deleted_at')
  157. {
  158. $this->whereNull($deletedAtColumn);
  159. return $this;
  160. }
  161. /**
  162. * Only include soft deleted models during the existence check.
  163. *
  164. * @param string $deletedAtColumn
  165. * @return $this
  166. */
  167. public function onlyTrashed($deletedAtColumn = 'deleted_at')
  168. {
  169. $this->whereNotNull($deletedAtColumn);
  170. return $this;
  171. }
  172. /**
  173. * Register a custom query callback.
  174. *
  175. * @param \Closure $callback
  176. * @return $this
  177. */
  178. public function using(Closure $callback)
  179. {
  180. $this->using[] = $callback;
  181. return $this;
  182. }
  183. /**
  184. * Get the custom query callbacks for the rule.
  185. *
  186. * @return array
  187. */
  188. public function queryCallbacks()
  189. {
  190. return $this->using;
  191. }
  192. /**
  193. * Format the where clauses.
  194. *
  195. * @return string
  196. */
  197. protected function formatWheres()
  198. {
  199. return (new Collection($this->wheres))
  200. ->map(fn ($where) => $where['column'].','.'"'.str_replace('"', '""', $where['value']).'"')
  201. ->implode(',');
  202. }
  203. }