Showing
4 changed files
with
441 additions
and
0 deletions
Docs/Rules/PHPCoding/BaseModel.php
0 → 100644
1 | +<?php | ||
2 | +/** | ||
3 | + * Created by Qingger Corp. | ||
4 | + * User: jsspf | ||
5 | + * Date: 2017/5/5 | ||
6 | + * Time: 15:37 | ||
7 | + */ | ||
8 | +namespace App\Models; | ||
9 | + | ||
10 | +use App\Exceptions\ECException; | ||
11 | +use App\Exceptions\ModelException; | ||
12 | +use App\Library\AppUtils\UtilToolMethods; | ||
13 | +use App\Library\VariDefines\Common\GlobalSysEnum; | ||
14 | +use App\Library\VariDefines\ErrorCodes\GlobalErrCode; | ||
15 | +use App\Services\Cache\AppCacheManager; | ||
16 | +use Illuminate\Database\Query\Builder; | ||
17 | +use Illuminate\Database\Eloquent\Model; | ||
18 | +use Illuminate\Database\Query\Expression; | ||
19 | +use Illuminate\Support\Collection; | ||
20 | +use Illuminate\Support\Facades\App; | ||
21 | +use Windwalker\String\SimpleTemplate; | ||
22 | +use Log; | ||
23 | +use DB; | ||
24 | + | ||
25 | +/** | ||
26 | + * Class BaseModel | ||
27 | + * @package App\Models | ||
28 | + * | ||
29 | + * @method Builder where(string|array|\Closure $column, string $operator = null, mixed $value = null, string $boolean = 'and') | ||
30 | + * @method Builder orWhere(string $column, string $operator = null, mixed $value = null) | ||
31 | + * @method Builder whereRaw(string $sql, array $bindings = array(), string $boolean = 'and') | ||
32 | + * @method Builder orWhereRaw(string $sql, array $bindings = array()) | ||
33 | + * @method Builder whereBetween(string $column, array $values, string $boolean = 'and', bool $not = false) | ||
34 | + * @method Builder orWhereBetween(string $column, array $values) | ||
35 | + * @method Builder whereNotBetween(string $column, array $values, string $boolean = 'and') | ||
36 | + * @method Builder orWhereNotBetween(string $column, array $values) | ||
37 | + * @method Builder whereNested(\Closure $callback, string $boolean = 'and') | ||
38 | + * @method addNestedWhereQuery(Builder|Builder $query, string $boolean = 'and') | ||
39 | + * @method Builder whereExists(\Closure $callback, string $boolean = 'and', bool $not = false) | ||
40 | + * @method Builder orWhereExists(\Closure $callback, bool $not = false) | ||
41 | + * @method Builder whereNotExists(\Closure $callback, string $boolean = 'and') | ||
42 | + * @method Builder orWhereNotExists(\Closure $callback) | ||
43 | + * @method Builder whereIn(string $column, mixed $values, string $boolean = 'and', bool $not = false) | ||
44 | + * @method Builder orWhereIn(string $column, mixed $values) | ||
45 | + * @method Builder whereNotIn(string $column, mixed $values, string $boolean = 'and') | ||
46 | + * @method Builder orWhereNotIn(string $column, mixed $values) | ||
47 | + * @method Builder whereNull(string $column, string $boolean = 'and', bool $not = false) | ||
48 | + * @method Builder whereNotNull(string $column, string $boolean = 'and') | ||
49 | + * @method Builder orWhereNotNull(string $column) | ||
50 | + * @method Builder whereDate(string $column, string $operator, int $value, string $boolean = 'and') | ||
51 | + * @method Builder whereDay(string $column, string $operator, int $value, string $boolean = 'and') | ||
52 | + * @method Builder whereMonth(string $column, string $operator, int $value, string $boolean = 'and') | ||
53 | + * @method Builder whereYear(string $column, string $operator, int $value, string $boolean = 'and') | ||
54 | + * @method $this dynamicWhere(string $method, string $parameters) | ||
55 | + * @method Builder groupBy() | ||
56 | + * @method Builder having(string $column, string $operator = null, string $value = null, string $boolean = 'and') | ||
57 | + * @method Builder orHaving(string $column, string $operator = null, string $value = null) | ||
58 | + * @method $this havingRaw(string $sql, array $bindings = array(), string $boolean = 'and') | ||
59 | + * @method Builder orHavingRaw(string $sql, array $bindings = array()) | ||
60 | + * @method Builder orderBy(string $column, string $direction = 'asc') | ||
61 | + * @method Builder latest(string $column = 'created_at') | ||
62 | + * @method Builder oldest(string $column = 'created_at') | ||
63 | + * @method Builder orderByRaw(string $sql, array $bindings = array()) | ||
64 | + * @method $this offset(int $value) | ||
65 | + * @method Builder skip(int $value) | ||
66 | + * @method Builder limit(int $value) | ||
67 | + * @method Builder take(int $value) | ||
68 | + * @method Builder forPage(int $page, int $perPage = 15) | ||
69 | + * @method Builder union(Builder|\Closure $query, bool $all = false) | ||
70 | + * @method Builder unionAll(Builder|\Closure $query) | ||
71 | + * @method $this lock(bool $value = true) | ||
72 | + * @method Builder lockForUpdate() | ||
73 | + * @method Builder sharedLock() | ||
74 | + * @method string toSql() | ||
75 | + * @method mixed find(int $id, array $columns = array('*')) | ||
76 | + * @method mixed first(array $columns = array('*')) | ||
77 | + * @method mixed value(string $column) | ||
78 | + * @method $this select(array|mixed $columns = array('*')) | ||
79 | + * @method $this distinct() | ||
80 | + * @method $this join(string $table, string $one, string $operator = null, string $two = null, string $type = 'inner', bool $where = false) | ||
81 | + * @method Builder joinWhere(string $table, string $one, string $operator, string $two, string $type = 'inner') | ||
82 | + * @method Builder leftJoin(string $table, string $first, string $operator = null, string $second = null) | ||
83 | + * @method Builder leftJoinWhere(string $table, string $one, string $operator, string $two) | ||
84 | + * @method Builder rightJoin(string $table, string $first, string $operator = null, string $second = null) | ||
85 | + * @method Builder rightJoinWhere(string $table, string $one, string $operator, string $two) | ||
86 | + * @method Collection get(array $columns = array('*')) | ||
87 | + * @method array lists(string $column, string|null $key = null) | ||
88 | + * @method string implode(string $column, string $glue = '') | ||
89 | + * @method bool exists() | ||
90 | + * @method int count(string $columns = '*') | ||
91 | + * @method mixed min(string $column) | ||
92 | + * @method mixed max(string $column) | ||
93 | + * @method mixed sum(string $column) | ||
94 | + * @method mixed avg(string $column) | ||
95 | + * @method mixed average(string $column) | ||
96 | + * @method mixed aggregate(string $function, array $columns = array('*')) | ||
97 | + * @method float|int numericAggregate(string $function, array $columns = array('*')) | ||
98 | + * @method bool insert(array $values) | ||
99 | + * @method int insertGetId(array $values, string $sequence = null) | ||
100 | + * @method void truncate() | ||
101 | + * @method Builder newQuery() | ||
102 | + * @method void mergeWheres(array $wheres, array $bindings) | ||
103 | + * @method Expression raw(mixed $value) | ||
104 | + * | ||
105 | + */ | ||
106 | +class BaseModel extends Model | ||
107 | +{ | ||
108 | + use UtilToolMethods; | ||
109 | + protected $table=''; | ||
110 | + protected $defautCacheTime = 60; | ||
111 | + | ||
112 | + /** | ||
113 | + * 缓存管理器 | ||
114 | + * @var AppCacheManager | ||
115 | + */ | ||
116 | + protected $appCacheManager = null; | ||
117 | + | ||
118 | + /** | ||
119 | + * 对Model的操作行为 | ||
120 | + * @var string | ||
121 | + */ | ||
122 | + private $modelAction = GlobalSysEnum::STS_CREATED; | ||
123 | + | ||
124 | + | ||
125 | + public function __construct(array $attributes = []) | ||
126 | + { | ||
127 | + parent::__construct($attributes); | ||
128 | + $this->appCacheManager = App::make(AppCacheManager::class); | ||
129 | + } | ||
130 | + | ||
131 | + public function getPrimaryKey() { | ||
132 | + return $this->primaryKey; | ||
133 | + } | ||
134 | + | ||
135 | + public function getMyId() { | ||
136 | + return $this->{$this->primaryKey}; | ||
137 | + } | ||
138 | + | ||
139 | + public function getTable() { | ||
140 | + return $this->table; | ||
141 | + } | ||
142 | + | ||
143 | + public function getColItem($item) { | ||
144 | + return $this->table.".".$item; | ||
145 | + } | ||
146 | + | ||
147 | + public function formatArray($queryResult) | ||
148 | + { | ||
149 | + return json_decode(json_encode($queryResult), true); | ||
150 | + } | ||
151 | + | ||
152 | + /** | ||
153 | + * 基础的条件查询,支持以下几种方式 | ||
154 | + * $this->getQueryByConditions(array( | ||
155 | + * 'id' => '1', // id==1 | ||
156 | + * 'col1' => [1,2,3], // col1 in (1,2,3) | ||
157 | + * 'col2' => [ 'sign' => '!=' , value=>3 ] // col2 != 3 | ||
158 | + * 'col3' => [ 'operator=>'whereNotIn', value=[1,2,3] ] // col3 not in (1,2,3) | ||
159 | + * )); | ||
160 | + * @param array $conditions | ||
161 | + * | ||
162 | + * @param array $selectItems | ||
163 | + * @param bool $isDistinct | ||
164 | + * @return Builder | ||
165 | + */ | ||
166 | + public function getQueryByConditions(Array $conditions,Array $selectItems=[],$isDistinct=false) { | ||
167 | + $query = $this; | ||
168 | + foreach ($conditions as $key=>$val) { | ||
169 | + if(is_array($val) && isset($val['operator'])) { | ||
170 | + $query = $query->{$val['operator']}($val['value']); | ||
171 | + }elseif(is_array($val) && isset($val['sign'])) { | ||
172 | + $query = $query->where($key,$val['sign'],$val['value']); | ||
173 | + }elseif(is_array($val)){ | ||
174 | + $query = $query->whereIn($key,$val); | ||
175 | + }else{ | ||
176 | + $query = $query->where($key,$val); | ||
177 | + } | ||
178 | + } | ||
179 | + if(!empty($selectItems)) { | ||
180 | + $query = $query->select($selectItems); | ||
181 | + } | ||
182 | + if($isDistinct) { | ||
183 | + $query = $query->distinct(); | ||
184 | + } | ||
185 | + | ||
186 | + return $query; | ||
187 | + } | ||
188 | + | ||
189 | + | ||
190 | + | ||
191 | + /* override */ | ||
192 | + public function checkValidItem(Array $conditions) { | ||
193 | + return $this->where($conditions)->count(); | ||
194 | + } | ||
195 | + | ||
196 | + /** | ||
197 | + * 根据primaryId更新数据字段 | ||
198 | + * @param array $updateItems | ||
199 | + * @param $idVal | ||
200 | + * @return int | ||
201 | + */ | ||
202 | + public function updateItemsByPrimaryId(Array $updateItems,$idVal) { | ||
203 | + return DB::table($this->table)->where($this->primaryKey,$idVal)->update($updateItems); | ||
204 | + } | ||
205 | + | ||
206 | + /** | ||
207 | + * 根据条件更新数据字段 | ||
208 | + * @param array $updateItems | ||
209 | + * @param array $conditions | ||
210 | + * @return int | ||
211 | + */ | ||
212 | + public function updateItemsByConditions(Array $updateItems,Array $conditions) { | ||
213 | + return DB::table($this->table)->where($conditions)->update($updateItems); | ||
214 | + } | ||
215 | + | ||
216 | + /** | ||
217 | + * 检查模型的ID数据是否存在,即是否真正的实体 | ||
218 | + * @return bool | ||
219 | + * @throws ModelException | ||
220 | + */ | ||
221 | + protected function checkObjectIdExist() { | ||
222 | + if(!isset($this->primaryKey) || !isset($this->{$this->primaryKey})) { | ||
223 | + throw new ModelException('Object Not Found Error',GlobalErrCode::ERR_MODEL_OBJECT_NOT_FOUND); | ||
224 | + } | ||
225 | + return true; | ||
226 | + } | ||
227 | + | ||
228 | + | ||
229 | + /** | ||
230 | + * 根据主键获得实例 | ||
231 | + * @param $keyId | ||
232 | + * @return BaseModel | ||
233 | + */ | ||
234 | + public function getInstanceByKeyId($keyId) { | ||
235 | + return $this->find($keyId); | ||
236 | + } | ||
237 | + | ||
238 | + /** | ||
239 | + * @return mixed|null | ||
240 | + */ | ||
241 | + public function getMyUpdatedAt() { | ||
242 | + return isset($this->updated_at) ? $this->updated_at : null; | ||
243 | + } | ||
244 | + | ||
245 | + /** | ||
246 | + * @return mixed|null | ||
247 | + */ | ||
248 | + public function getMyCreatedAt() { | ||
249 | + return isset($this->created_at) ? $this->created_at : null; | ||
250 | + } | ||
251 | + | ||
252 | + | ||
253 | + /** | ||
254 | + * 检查ID对应的数据实例是否存在 | ||
255 | + * @param $id | ||
256 | + * @return true | ||
257 | + * @throws ECException | ||
258 | + */ | ||
259 | + public function checkIdExists($id) { | ||
260 | + $instance = $this->find($id); | ||
261 | + if(!$instance) { | ||
262 | + throw new ECException('数据对应的ID不存在:'.$id,GlobalErrCode::ERR_DATA_NOT_FOUND); | ||
263 | + } | ||
264 | + return true; | ||
265 | + } | ||
266 | + | ||
267 | + /** | ||
268 | + * @override | ||
269 | + * @param array $options | ||
270 | + * @return bool | ||
271 | + */ | ||
272 | + public function save(array $options = []) | ||
273 | + { | ||
274 | + if(isset($this->{$this->primaryKey})) { | ||
275 | + $this->modelAction = GlobalSysEnum::STS_UPDATED; | ||
276 | + } else { | ||
277 | + $this->modelAction = GlobalSysEnum::STS_CREATED; | ||
278 | + } | ||
279 | + Log::debug(SimpleTemplate::render('Model Save for {{table}} - {{action}}',[ | ||
280 | + 'table' => $this->table, | ||
281 | + 'action' => $this->modelAction | ||
282 | + ]),['data'=>toArray($this)]); | ||
283 | + | ||
284 | + | ||
285 | + return parent::save($options); | ||
286 | + } | ||
287 | + | ||
288 | + /** | ||
289 | + * @override | ||
290 | + * @return bool|null | ||
291 | + */ | ||
292 | + public function delete() | ||
293 | + { | ||
294 | + $this->modelAction = GlobalSysEnum::STS_DELETED; | ||
295 | + Log::debug(SimpleTemplate::render('Model Delete for {{table}}',[ | ||
296 | + 'table' => $this->table | ||
297 | + ]),['id'=>$this->getMyId()]); | ||
298 | + | ||
299 | + return parent::delete(); | ||
300 | + } | ||
301 | + | ||
302 | + | ||
303 | + /** | ||
304 | + * 基础方法,获得数据所归属的企业 | ||
305 | + * @return mixed|null | ||
306 | + */ | ||
307 | + public function getMyGroupId() { | ||
308 | + return isset($this->group_id) ? $this->group_id : null; | ||
309 | + } | ||
310 | + | ||
311 | + | ||
312 | + /** | ||
313 | + * 获得对象的Hash值 | ||
314 | + * @param $objectId | ||
315 | + * @return string | null | ||
316 | + */ | ||
317 | + protected function getObjectHashValue($objectId) { | ||
318 | + $fullClassName = $this->getFullClassName(); | ||
319 | + $groupId = $this->getMyGroupId(); | ||
320 | + | ||
321 | + if(!isset($fullClassName) || !isset($groupId)) { | ||
322 | + return null; | ||
323 | + } | ||
324 | + | ||
325 | + return (new ODAObjectKeyHash())->getObjectKeyHash($groupId,$fullClassName,$objectId); | ||
326 | + } | ||
327 | + | ||
328 | + /** | ||
329 | + * 设置对象的Hash值 | ||
330 | + * @param $objectId | ||
331 | + * @param array $val | ||
332 | + * @return ODAObjectKeyHash|null | ||
333 | + */ | ||
334 | + protected function setObjectHash($objectId,array $val) { | ||
335 | + $fullClassName = $this->getFullClassName(); | ||
336 | + $groupId = $this->getMyGroupId(); | ||
337 | + | ||
338 | + if(!isset($fullClassName) || !isset($groupId) || empty($val)) { | ||
339 | + return null; | ||
340 | + } | ||
341 | + | ||
342 | + $valEncoding = $this->arrayEncode($val,GlobalSysEnum::SIGN_SHA1); | ||
343 | + | ||
344 | + return (new ODAObjectKeyHash())->setObjectKeyHash($groupId,$fullClassName,$objectId,$valEncoding); | ||
345 | + } | ||
346 | + | ||
347 | + | ||
348 | + /** | ||
349 | + * 检查对象的Hash是否存在,如不存在则存储Hash | ||
350 | + * @param BaseModel $baseModel | ||
351 | + * @param $keyId | ||
352 | + * @param array $value | ||
353 | + * @return bool | ||
354 | + */ | ||
355 | + protected function checkObjectExistAndStoreHash(BaseModel $baseModel, $keyId ,array $value) { | ||
356 | + if($baseModel) { | ||
357 | + $valEncodingHash = $this->arrayEncode($value,GlobalSysEnum::SIGN_SHA1); | ||
358 | + | ||
359 | + $storeValHash = $baseModel->getObjectHashValue($keyId); | ||
360 | + | ||
361 | + if(isset($storeValHash) && $storeValHash==$valEncodingHash) { | ||
362 | + return true; | ||
363 | + } else { | ||
364 | + $baseModel->setObjectHash($keyId,$value); | ||
365 | + } | ||
366 | + } | ||
367 | + return false; | ||
368 | + } | ||
369 | + | ||
370 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -147,3 +147,74 @@ class Group extends BaseModel | ... | @@ -147,3 +147,74 @@ class Group extends BaseModel |
147 | 147 | ||
148 | 148 | ||
149 | 149 | ||
150 | +<br/> | ||
151 | + | ||
152 | +--- | ||
153 | + | ||
154 | +<br/> | ||
155 | + | ||
156 | +## 2. Model必遵守规约 | ||
157 | + | ||
158 | +#### 2.1 所有的Model不允许直接从Model中继承,而是继承自BaseModel。 | ||
159 | + | ||
160 | +* BaseModel参考 [BaseModel](BaseModel.php) | ||
161 | + | ||
162 | +<br/> | ||
163 | + | ||
164 | +#### 2.2 Model层不允许出现警告错误 | ||
165 | + | ||
166 | +* 在phpstorm中,Model层内不允许出现黄色警告错误。如果有,必须想办法解决。 | ||
167 | +* first(), where(), get() 这些警告,已经在BaseModel中作出处理。 | ||
168 | + | ||
169 | +<br/> | ||
170 | + | ||
171 | +#### 2.3 每个函数必须要有注释 | ||
172 | + | ||
173 | +* 每个函数 **必须** 要有注释。且注释一定要完整准确,注释上 **不能** 出现波浪线. | ||
174 | + | ||
175 | + | ||
176 | + | ||
177 | +#### 2.4 必须确认函数参数 / 函数返回值 的类型(尤其是类型为对象/列表/数组时) | ||
178 | + | ||
179 | +* 当函数参数是 | ||
180 | + | ||
181 | + | ||
182 | + | ||
183 | +#### 2.5 函数命名的规范性 | ||
184 | + | ||
185 | +* 当函数用来定义ORM映射关系时 | ||
186 | +* 当函 | ||
187 | + | ||
188 | + | ||
189 | + | ||
190 | +#### 2.6 注释的写法 | ||
191 | + | ||
192 | + | ||
193 | + | ||
194 | +#### 2.7 Model层的作用及注意事项 | ||
195 | + | ||
196 | + | ||
197 | + | ||
198 | +#### 2.8 Service层的作用及注意事项 | ||
199 | + | ||
200 | +* 不要作底层的SQL语句查询 | ||
201 | +* 将业务和算法分离 | ||
202 | +* 清晰定义具体的业务逻辑 | ||
203 | +* | ||
204 | + | ||
205 | + | ||
206 | + | ||
207 | +#### 2.9 Controller层的作用及注意事项 | ||
208 | + | ||
209 | + | ||
210 | + | ||
211 | +#### 2.10 Model ORM关系的定义 | ||
212 | + | ||
213 | + | ||
214 | + | ||
215 | + | ||
216 | + | ||
217 | + | ||
218 | + | ||
219 | + | ||
220 | + | ... | ... |
This file is too large to display.
This file is too large to display.
-
Please register or login to post a comment