BaseRequest.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <?php namespace App\Http\Requests;
  2. // 表单验证
  3. use App\Exceptions\Api\ValidException;
  4. use Illuminate\Foundation\Http\FormRequest;
  5. // 验证器
  6. use Illuminate\Contracts\Validation\Validator;
  7. /**
  8. * 基础验证器
  9. *
  10. * 此验证器增加了验证场景的移除与添加等功能
  11. *
  12. */
  13. class BaseRequest extends FormRequest
  14. {
  15. // 场景列表
  16. protected $scenes = [];
  17. // 当前场景
  18. protected $currentScene;
  19. // 是否注入之后自动验证
  20. protected $autoValidate = false;
  21. // 场景需要移除的验证规则
  22. protected $remove = [];
  23. // 场景需要追加的验证规则
  24. protected $append = [];
  25. /**
  26. * 自动认证
  27. */
  28. public function authorize()
  29. {
  30. return true;
  31. }
  32. /**
  33. * 设置场景
  34. * @param string $scene
  35. * @return $this
  36. */
  37. public function scene($scene)
  38. {
  39. $this->currentScene = $scene;
  40. return $this;
  41. }
  42. /**
  43. * 覆盖自动验证方法
  44. */
  45. public function validateResolved()
  46. {
  47. // 注入之后自动验证开启则执行最终验证方法
  48. if ($this->autoValidate) $this->handleValidate();
  49. }
  50. /**
  51. * 验证方法
  52. * @param string $scene
  53. */
  54. public function validate($scene = '')
  55. {
  56. // 有场景参数。设置场景参数
  57. if ($scene) $this->currentScene = $scene;
  58. // 调用最终验证方法
  59. $this->handleValidate();
  60. }
  61. /**
  62. * 根据场景获取规则
  63. * @return array|mixed
  64. */
  65. public function getRules()
  66. {
  67. // 获取验证规则
  68. $rules = $this->container->call([$this, 'rules']);
  69. // 创建新规则
  70. $newRules = [];
  71. // 如果当前有场景并且存在场景字段,使用场景规则
  72. if ( $this->currentScene && isset($this->scenes[$this->currentScene]) ) {
  73. // 如果需要验证的场景字段是数组格式直接使用,否则做字符串切割成数组
  74. $sceneFields = is_array($this->scenes[$this->currentScene]) ? $this->scenes[$this->currentScene] : explode(',', $this->scenes[$this->currentScene]);
  75. // 循环场景字段
  76. foreach ($sceneFields as $field) {
  77. // 如果场景字段存在于验证规则中,
  78. if (array_key_exists($field, $rules)) $newRules[$field] = $rules[$field];
  79. }
  80. // 返回新规则
  81. return $this->handleRules($newRules);
  82. }
  83. // 没有场景定义数据,使用原规则
  84. return $this->handleRules($rules);
  85. }
  86. /**
  87. * 处理规则数据
  88. *
  89. * @return array|mixed
  90. */
  91. protected function handleRules($rules){
  92. // 循环需要增加的验证字段
  93. foreach ($this->append as $key => $rule) {
  94. // 规则中不存在需要增加的验证字段
  95. if ( !isset($rules[$key]) ) {
  96. // 添加到验证规则中
  97. $rules[$key] = $rule;
  98. }else{
  99. // 循环要添加规则数据
  100. foreach ( $rule as $string ) {
  101. // 要添加的数据
  102. $append = explode(':',$string);
  103. // 临时中转已存在的规则
  104. $tempRules = [];
  105. // 循环规则中的数据
  106. foreach (explode('|',$rules[$key]) as $tkey => $string) {
  107. // 切割规则与参数
  108. $temp = explode(':',$string);
  109. $tempRules[$temp['0']] = isset($temp['1']) ? $temp['1'] : null;
  110. }
  111. // 不存在的话,增加参数
  112. $tempRules[$append[0]] = isset($append['1']) ? $append['1'] : null;
  113. // 重新写入
  114. $r = [];
  115. // 循环规则中的数据
  116. foreach ( $tempRules as $tkey => $string) {
  117. $r[] = $tkey.':'.$string;
  118. }
  119. // 数据组合
  120. $rules[$key] = implode('|',$r);
  121. }
  122. }
  123. // 添加后删除
  124. unset($this->append[$key]);
  125. }
  126. // 循环删除的字段
  127. foreach ($this->remove as $key => $rule) {
  128. // 规则中存在字段才需要删除
  129. if ( !isset($rules[$key]) ) continue;
  130. // 如果字段为空,表示删除所有的验证规则
  131. if( !$rule ) {
  132. // 删除掉当前的字段
  133. unset($rules[$key]);
  134. // 跳出本次循环
  135. continue;
  136. }
  137. // 当前规则
  138. $newRule = explode('|',$rules[$key]);
  139. // 循环要删除规则数据
  140. foreach ( $rule as $remove ) {
  141. // 要移除的规则
  142. $remove = explode(':',$remove);
  143. // 循环当前规则
  144. foreach ( $newRule as $tkey => $string) {
  145. // 切割成数组
  146. $string = explode(':',$string);
  147. // 如果是要删除的规则
  148. if( $string[0] == $remove[0]) unset($newRule[$tkey]);
  149. }
  150. }
  151. // 重新赋值到规则
  152. $rules[$key] = implode('|',$newRule);
  153. // 添加后删除
  154. unset($this->remove[$key]);
  155. }
  156. // 返回最终规则
  157. return $rules;
  158. }
  159. /**
  160. * 移除某个字段的验证规则
  161. * @access public
  162. * @param string|array $field 字段名
  163. * @param mixed $rule 验证规则 null 移除所有规则
  164. * @return $this
  165. */
  166. public function remove($field, $rule = null)
  167. {
  168. if (is_array($field)) {
  169. foreach ($field as $key => $rule) {
  170. if (is_int($key)) {
  171. $this->remove($rule);
  172. } else {
  173. $this->remove($key, $rule);
  174. }
  175. }
  176. } else {
  177. if (is_string($rule)) {
  178. $rule = explode('|', $rule);
  179. }
  180. $this->remove[$field] = $rule;
  181. }
  182. return $this;
  183. }
  184. /**
  185. * 追加某个字段的验证规则
  186. * @access public
  187. * @param string|array $field 字段名
  188. * @param mixed $rule 验证规则
  189. * @return $this
  190. */
  191. public function append($field, $rule = null)
  192. {
  193. if (is_array($field)) {
  194. foreach ($field as $key => $rule) {
  195. $this->append($key, $rule);
  196. }
  197. } else {
  198. if (is_string($rule)) {
  199. $rule = explode('|', $rule);
  200. }
  201. $this->append[$field] = $rule;
  202. }
  203. return $this;
  204. }
  205. /**
  206. * 覆盖设置 自定义验证器
  207. * @param $factory
  208. * @return mixed
  209. */
  210. public function validator($factory)
  211. {
  212. return $factory->make(
  213. $this->validationData(),
  214. $this->getRules(),
  215. $this->messages(),
  216. $this->attributes()
  217. );
  218. }
  219. /**
  220. * 最终验证方法
  221. *
  222. */
  223. protected function handleValidate()
  224. {
  225. // 验证前准备
  226. $this->prepareForValidation();
  227. // 判断用户是否有请求权限,默认为有,如果没有权限,告知失败
  228. if (!$this->passesAuthorization()) $this->failedAuthorization();
  229. // 获取验证对象实例
  230. $instance = $this->getValidatorInstance();
  231. // 如果验证失败
  232. if ($instance->fails()) $this->failedValidation($instance);
  233. // 验证后处理
  234. $this->passedValidation();
  235. }
  236. /**
  237. * Handle a failed validation attempt.
  238. *
  239. * @param \Illuminate\Contracts\Validation\Validator $validator
  240. *
  241. * @throws \Illuminate\Validation\ValidationException
  242. */
  243. protected function failedValidation(Validator $validator)
  244. {
  245. // 获取提示信息
  246. $error = empty($validator->errors()->all()[0]) ? '' : $validator->errors()->all()[0];
  247. // 响应抛出
  248. throw new ValidException($error,$validator->errors()->toArray());
  249. }
  250. }