StoreFeeForm.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <?php
  2. namespace hd\models\IntraCity;
  3. use hd\models\BaseForm;
  4. use common\components\IntraCityExpress;
  5. /**
  6. * 同城配送查询运费表单验证
  7. */
  8. class StoreFeeForm extends BaseForm
  9. {
  10. // 订单相关字段
  11. public $orderId;
  12. // 用户信息字段
  13. public $user_name;
  14. public $user_phone;
  15. public $user_lng;
  16. public $user_lat;
  17. public $user_address;
  18. // 货物信息字段-1
  19. public $weight;
  20. public $price;
  21. public $packageNum;
  22. // 货物信息字段-2
  23. public $cargo_name;
  24. public $cargo_weight;
  25. public $cargo_price;
  26. public $cargo_type;
  27. public $cargo_num;
  28. // 订单信息字段
  29. public $wx_store_id;
  30. public $use_sandbox;
  31. public $cargo;
  32. /**
  33. * @inheritdoc
  34. */
  35. public function rules()
  36. {
  37. return [
  38. // 必填字段验证
  39. [['orderId', 'user_name', 'user_phone', 'user_lng', 'user_lat', 'user_address', 'weight', 'price', 'packageNum'], 'required'],
  40. // 订单ID验证
  41. ['orderId', 'integer', 'min' => 1, 'message' => '订单ID必须是正整数'],
  42. // 用户姓名验证
  43. ['user_name', 'string', 'max' => 64, 'message' => '收货人姓名长度不能超过64字符'],
  44. ['user_name', 'trim'],
  45. ['user_name', 'filter', 'filter' => function($value) {
  46. return strip_tags($value); // 过滤HTML标签
  47. }],
  48. ['user_name', 'match', 'pattern' => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9\s]{1,64}$/u', 'message' => '收货人姓名只能包含中文、英文和数字'],
  49. // 用户电话验证
  50. ['user_phone', 'string'],
  51. ['user_phone', 'match', 'pattern' => '/^(1[3-9]\d{9}|^0\d{2,3}\d{7,8})$/', 'message' => '手机号或固话格式不正确'],
  52. // 经纬度验证
  53. ['user_lng', 'number', 'min' => -180, 'max' => 180, 'message' => '经度范围必须在-180到180之间'],
  54. ['user_lat', 'number', 'min' => -90, 'max' => 90, 'message' => '纬度范围必须在-90到90之间'],
  55. // 用户地址验证
  56. ['user_address', 'string', 'max' => 512, 'message' => '收货地址长度不能超过512字符'],
  57. ['user_address', 'trim'],
  58. ['user_address', 'filter', 'filter' => function($value) {
  59. return strip_tags($value); // 过滤HTML标签
  60. }],
  61. // 货物重量验证(单位:克)
  62. ['weight', 'number', 'min' => 0.1, 'max' => 30, 'message' => '货物重量必须在0.1-30千克之间'],
  63. // 货物价格验证(单位:分)
  64. ['price', 'number', 'min' => 0, 'max' => 1000000, 'message' => '货物价格必须在0-100万元之间'],
  65. // 包裹数量验证
  66. ['packageNum', 'integer', 'min' => 1, 'max' => 10000, 'message' => '包裹数量必须在1-10000之间'],
  67. // 自定义验证规则
  68. ['user_lng', 'validateCoordinates'],
  69. ['weight', 'validateWeight'],
  70. ['price', 'validatePrice'],
  71. ['cargo', 'validateCargo'],
  72. ];
  73. }
  74. /**
  75. * @inheritdoc
  76. */
  77. public function attributeLabels()
  78. {
  79. return [
  80. 'wx_store_id' => '微信门店ID',
  81. 'use_sandbox' => '是否使用沙盒环境',
  82. 'cargo' => '货物信息',
  83. 'orderId' => '订单ID',
  84. 'user_name' => '收货人姓名',
  85. 'user_phone' => '收货人电话',
  86. 'user_lng' => '收货人经度',
  87. 'user_lat' => '收货人纬度',
  88. 'user_address' => '收货人地址',
  89. 'weight' => '货物重量',
  90. 'price' => '货物价格',
  91. 'packageNum' => '包裹数量',
  92. ];
  93. }
  94. /**
  95. * 自定义验证:验证经纬度是否在合理范围内
  96. */
  97. public function validateCoordinates($attribute, $params)
  98. {
  99. if (!empty($this->user_lng) && !empty($this->user_lat)) {
  100. // 验证是否为中国境内坐标(粗略验证)
  101. $lng = floatval($this->user_lng);
  102. $lat = floatval($this->user_lat);
  103. // 中国境内经纬度大致范围:经度 73°-135°,纬度 18°-54°
  104. if ($lng < 73 || $lng > 135 || $lat < 18 || $lat > 54) {
  105. $this->addError($attribute, '坐标位置似乎不在服务范围内');
  106. }
  107. }
  108. }
  109. /**
  110. * 自定义验证:验证货物重量限制
  111. */
  112. public function validateWeight($attribute, $params)
  113. {
  114. if (!empty($this->weight)) {
  115. $weight = floatval($this->weight);
  116. // 一般同城配送重量限制(例如:不超过30公斤)
  117. if ($weight > 30) { // 30公斤
  118. $this->addError($attribute, '货物重量不能超过30公斤');
  119. }
  120. }
  121. }
  122. /**
  123. * 自定义验证:验证货物价格合理性
  124. */
  125. public function validatePrice($attribute, $params)
  126. {
  127. if (!empty($this->price)) {
  128. $price = intval($this->price);
  129. // 货物价格上限验证(例如:不超过100万)
  130. if ($price > 1000000) {
  131. $this->addError($attribute, '货物价值过高,请联系客服');
  132. }
  133. }
  134. }
  135. public function validateCargo($attribute, $params)
  136. {
  137. // 验证货物信息是否为数组且包含必要字段
  138. if (empty($this->cargo) || !is_array($this->cargo)) {
  139. $this->addError($attribute, '货物信息必须是数组格式');
  140. return;
  141. }
  142. // 检查必要字段是否存在
  143. $requiredFields = ['cargo_name', 'cargo_weight', 'cargo_price', 'cargo_type', 'cargo_num'];
  144. $missingFields = [];
  145. foreach ($requiredFields as $field) {
  146. if (!isset($this->cargo[$field]) || empty($this->cargo[$field])) {
  147. $missingFields[] = $field;
  148. }
  149. }
  150. if (!empty($missingFields)) {
  151. $this->addError($attribute, '货物信息缺少必要字段:' . implode('、', $missingFields));
  152. return;
  153. }
  154. // 验证货物重量
  155. $weight = floatval($this->cargo['cargo_weight']);
  156. if ($weight <= 0 || $weight > 30000) {
  157. $this->addError($attribute, '货物重量必须在1-30000克之间');
  158. }
  159. // 验证货物价格
  160. $price = intval($this->cargo['cargo_price']);
  161. if ($price < 0 || $price > 1000000000) {
  162. $this->addError($attribute, '货物价格必须在0-100万元之间');
  163. }
  164. // 验证货物数量
  165. $num = intval($this->cargo['cargo_num']);
  166. if ($num <= 0 || $num > 1000) {
  167. $this->addError($attribute, '货物数量必须在1-1000之间');
  168. }
  169. // 验证货物名称
  170. $name = trim($this->cargo['cargo_name']);
  171. if (mb_strlen($name, 'UTF-8') > 100) {
  172. $this->addError($attribute, '货物名称长度不能超过100个字符');
  173. }
  174. }
  175. /**
  176. * 场景定义 -- 不同场景下,需要验证的字段不同
  177. * 1. store_fee 查询运费场景
  178. * 2. query_fee 查询运费场景
  179. */
  180. public function scenarios()
  181. {
  182. $scenarios = parent::scenarios();
  183. // 查询运费场景
  184. $scenarios['store_fee'] = [
  185. 'orderId', 'user_name', 'user_phone', 'user_lng', 'user_lat',
  186. 'user_address', 'weight', 'price', 'packageNum'
  187. ];
  188. // 查询运费场景
  189. $scenarios['query_fee'] = [
  190. 'wx_store_id', 'user_name', 'user_phone', 'user_lng', 'user_lat',
  191. 'user_address', 'cargo', 'use_sandbox'
  192. ];
  193. return $scenarios;
  194. }
  195. /**
  196. * 在验证前执行额外的自定义验证
  197. */
  198. // public function beforeValidate()
  199. // {
  200. // if (parent::beforeValidate()) {
  201. // return true;
  202. // }
  203. // return false;
  204. // }
  205. /**
  206. * 在验证后执行额外的自定义验证
  207. */
  208. // public function afterValidate()
  209. // {
  210. // // 添加自定义验证规则
  211. // $this->validateCoordinates('user_lng', []);
  212. // $this->validateWeight('weight', []);
  213. // $this->validatePrice('price', []);
  214. // parent::afterValidate();
  215. // }
  216. }