1: | <?php |
2: | |
3: | namespace ZDB ; |
4: | |
5: | |
6: | |
7: | |
8: | |
9: | |
10: | abstract class Entity |
11: | { |
12: | protected $fields = array(); |
13: | |
14: | |
15: | |
16: | |
17: | |
18: | |
19: | |
20: | |
21: | |
22: | public function __construct($row = null) { |
23: | $this->init(); |
24: | if (is_array($row)) { |
25: | $this->fields = array_merge($this->fields, $row); |
26: | } |
27: | } |
28: | |
29: | |
30: | |
31: | |
32: | |
33: | protected function init() { |
34: | $meta = $this->getMetadata(); |
35: | $this->{$meta['keyfield']} = 0; |
36: | } |
37: | |
38: | |
39: | |
40: | |
41: | |
42: | |
43: | |
44: | |
45: | |
46: | |
47: | |
48: | protected static function getMetadata() { |
49: | $class = new \ReflectionClass(get_called_class()); |
50: | $doc = $class->getDocComment(); |
51: | preg_match_all('/@([a-z0-9_-]+)=([^\n]+)/is', $doc, $arr); |
52: | if (is_array($arr)) { |
53: | $reg_arr = array_combine($arr[1], $arr[2]); |
54: | |
55: | $table = trim($reg_arr['table']); |
56: | $view = trim($reg_arr['view'] ?? ''); |
57: | $keyfield = trim($reg_arr['keyfield']); |
58: | |
59: | |
60: | if (strlen($table) > 0 && strlen($keyfield) > 0) { |
61: | $retarr = array(); |
62: | $retarr['table'] = $table; |
63: | $retarr['keyfield'] = $keyfield; |
64: | if (strlen($view) > 0) { |
65: | $retarr['view'] = $view; |
66: | } |
67: | |
68: | return $retarr; |
69: | } |
70: | } |
71: | |
72: | |
73: | throw new ZDBException('getMetadata должен быть перегружен'); |
74: | } |
75: | |
76: | |
77: | |
78: | |
79: | |
80: | |
81: | public static function load($param, $fields='*') { |
82: | if($param ==null) { |
83: | return null; |
84: | } |
85: | if(is_string($param )) { |
86: | if(strlen($param )==0) { |
87: | return null; |
88: | } |
89: | } |
90: | $row = array(); |
91: | $class = get_called_class(); |
92: | |
93: | $meta = $class::getMetadata(); |
94: | $table = isset($meta['view']) ? $meta['view'] : $meta['table']; |
95: | $conn = DB::getConnect(); |
96: | if (is_numeric($param)) { |
97: | $row = $conn->GetRow("select {$fields} from {$table} where {$meta['keyfield']} = " . $param); |
98: | } elseif (is_array($param)) { |
99: | $row = $param; |
100: | } |
101: | |
102: | if (count($row) == 0) { |
103: | return null; |
104: | } |
105: | $obj = new $class(); |
106: | |
107: | $obj->setData($row); |
108: | $obj->afterLoad(); |
109: | return $obj; |
110: | } |
111: | |
112: | |
113: | |
114: | |
115: | |
116: | |
117: | public static function findCnt($where = "") { |
118: | $class = get_called_class(); |
119: | $meta = $class::getMetadata(); |
120: | $conn = DB::getConnect(); |
121: | |
122: | $table = isset($meta['view']) ? $meta['view'] : $meta['table']; |
123: | $sql = "select coalesce(count({$meta['keyfield']}),0) as cnt from " . $table; |
124: | |
125: | $cnst = static::getConstraint(); |
126: | if(strlen($cnst) >0) { |
127: | if(strlen($where)==0) { |
128: | $where = $cnst; |
129: | } else { |
130: | $where = "({$cnst}) and ({$where}) "; |
131: | } |
132: | } |
133: | if (strlen($where) > 0) { |
134: | $sql .= " where " . $where; |
135: | } |
136: | |
137: | |
138: | return $conn->getOne($sql); |
139: | } |
140: | |
141: | |
142: | |
143: | |
144: | public static function findBySql($sql) { |
145: | |
146: | $class = get_called_class(); |
147: | $meta = $class::getMetadata(); |
148: | |
149: | $conn = DB::getConnect(); |
150: | $list = array(); |
151: | |
152: | $rs = $conn->Execute($sql); |
153: | |
154: | foreach ($rs as $row) { |
155: | $item = new $class(); |
156: | $item->setData($row); |
157: | $list[$row[$meta['keyfield']]] = $item; |
158: | $list[$row[$meta['keyfield']]]->afterLoad(); |
159: | } |
160: | return $list; |
161: | } |
162: | |
163: | |
164: | |
165: | |
166: | |
167: | |
168: | |
169: | |
170: | |
171: | |
172: | |
173: | |
174: | public static function findArray($fieldname, $where = '', $orderbyfield = null, $count = -1, $offset = -1) { |
175: | |
176: | $class = get_called_class(); |
177: | $meta = $class::getMetadata(); |
178: | $table = isset($meta['view']) ? $meta['view'] : $meta['table']; |
179: | $conn = DB::getConnect(); |
180: | |
181: | $sql = "select {$meta['keyfield']} ,{$fieldname} as _field_ from " . $table; |
182: | |
183: | |
184: | $cnst = static::getConstraint(); |
185: | if(strlen($cnst ?? '') >0) { |
186: | if(strlen($where ?? '')==0) { |
187: | $where = $cnst; |
188: | } else { |
189: | $where = "({$cnst}) and ({$where}) "; |
190: | |
191: | } |
192: | } |
193: | |
194: | if (strlen(trim($where ?? '')) > 0) { |
195: | $sql .= " where " . $where; |
196: | } |
197: | $orderbyfield = trim($orderbyfield ?? '') ; |
198: | if(trim($orderbyfield)=='asc') { |
199: | $orderbyfield=''; |
200: | } |
201: | if(trim($orderbyfield)=='desc') { |
202: | $orderbyfield=''; |
203: | } |
204: | if (strlen($orderbyfield) > 0) { |
205: | $sql .= " order by " . $orderbyfield; |
206: | } |
207: | |
208: | if ($offset >= 0 or $count >= 0) { |
209: | $rs = $conn->SelectLimit($sql, $count, $offset); |
210: | } else { |
211: | $rs = $conn->Execute($sql); |
212: | } |
213: | $list = array(); |
214: | foreach ($rs as $row) { |
215: | |
216: | $list[$row[$meta['keyfield']]] = $row['_field_']; |
217: | |
218: | } |
219: | return $list; |
220: | } |
221: | |
222: | |
223: | |
224: | |
225: | |
226: | |
227: | |
228: | |
229: | |
230: | |
231: | |
232: | |
233: | |
234: | |
235: | public static function find($where = '', $orderbyfield = null, $count = -1, $offset = -1, $fields='') : array { |
236: | $list = []; |
237: | |
238: | foreach( self::findYield($where , $orderbyfield , $count , $offset , $fields) as $k=>$v ){ |
239: | $list[$k]=$v ; |
240: | } |
241: | |
242: | return $list; |
243: | } |
244: | |
245: | |
246: | |
247: | |
248: | |
249: | |
250: | |
251: | |
252: | |
253: | |
254: | |
255: | |
256: | public static function findYield($where = '', $orderbyfield = null, $count = -1, $offset = -1, $fields='') { |
257: | if(strlen($fields)==0) { |
258: | $fields ="*"; |
259: | } |
260: | |
261: | $class = get_called_class(); |
262: | $meta = $class::getMetadata(); |
263: | $table = isset($meta['view']) ? $meta['view'] : $meta['table']; |
264: | $conn = DB::getConnect(); |
265: | $list = array(); |
266: | $sql = "select {$fields} from " . $table; |
267: | |
268: | $cnst = static::getConstraint(); |
269: | if(strlen($cnst ?? '') >0) { |
270: | if(strlen($where ?? '')==0) { |
271: | $where = $cnst; |
272: | } else { |
273: | $where = "({$cnst}) and ({$where}) "; |
274: | |
275: | } |
276: | } |
277: | |
278: | if (strlen(trim($where ?? '')) > 0) { |
279: | $sql .= " where " . $where; |
280: | } |
281: | $orderbyfield = trim($orderbyfield ?? '') ; |
282: | if(trim($orderbyfield ?? '')=='asc') { |
283: | $orderbyfield=''; |
284: | } |
285: | if(trim($orderbyfield ?? '')=='desc') { |
286: | $orderbyfield=''; |
287: | } |
288: | if (strlen($orderbyfield ?? '') > 0) { |
289: | $sql .= " order by " . $orderbyfield; |
290: | } |
291: | |
292: | if ($offset >= 0 or $count >= 0) { |
293: | $rs = $conn->SelectLimit($sql, $count, $offset); |
294: | } else { |
295: | $rs = $conn->Execute($sql); |
296: | } |
297: | |
298: | foreach ($rs as $row) { |
299: | $item = new $class(); |
300: | $item->setData($row); |
301: | $item->afterLoad(); |
302: | yield $row[$meta['keyfield']] => $item; |
303: | |
304: | } |
305: | |
306: | } |
307: | |
308: | |
309: | |
310: | |
311: | |
312: | |
313: | |
314: | |
315: | public static function getOne($field, $where = "") { |
316: | $class = get_called_class(); |
317: | $meta = $class::getMetadata(); |
318: | $conn = DB::getConnect(); |
319: | |
320: | $table = isset($meta['view']) ? $meta['view'] : $meta['table']; |
321: | $sql = "select {$field} from " . $table; |
322: | |
323: | $cnst = static::getConstraint(); |
324: | if(strlen($cnst) >0) { |
325: | if(strlen($where)==0) { |
326: | $where = $cnst; |
327: | } else { |
328: | $where = "({$cnst}) and ({$where}) "; |
329: | |
330: | } |
331: | } |
332: | |
333: | if (strlen($where) > 0) { |
334: | $sql .= " where " . $where; |
335: | } |
336: | |
337: | |
338: | return $conn->getOne($sql); |
339: | } |
340: | |
341: | |
342: | |
343: | |
344: | |
345: | |
346: | public static function getFirst($where = "", $orderbyfield = null, $fields='') { |
347: | $list = self::find($where, $orderbyfield, 1, -1, $fields); |
348: | |
349: | if (count($list) == 0) { |
350: | return null; |
351: | } |
352: | |
353: | return array_pop($list); |
354: | |
355: | |
356: | } |
357: | |
358: | |
359: | |
360: | |
361: | |
362: | |
363: | public static function delete($id) { |
364: | $class = get_called_class(); |
365: | $meta = $class::getMetadata(); |
366: | |
367: | if ($id>0) { |
368: | |
369: | $obj = $class::load($id); |
370: | } |
371: | |
372: | if ($obj instanceof Entity) { |
373: | $allowdelete = $obj->beforeDelete(); |
374: | if (strlen($allowdelete)>0) { |
375: | |
376: | return $allowdelete; |
377: | } |
378: | |
379: | $sql = "delete from {$meta['table']} where {$meta['keyfield']} = " . $id; |
380: | $conn = DB::getConnect(); |
381: | $conn->Execute($sql); |
382: | $obj->afterDelete(); |
383: | return ""; |
384: | } |
385: | |
386: | |
387: | } |
388: | |
389: | |
390: | |
391: | |
392: | |
393: | |
394: | protected function beforeDelete() { |
395: | return ""; |
396: | } |
397: | |
398: | |
399: | |
400: | |
401: | |
402: | |
403: | protected function afterDelete() { |
404: | |
405: | } |
406: | |
407: | |
408: | |
409: | |
410: | |
411: | |
412: | |
413: | |
414: | |
415: | public static function qstr($str) { |
416: | $conn = DB::getConnect(); |
417: | return $conn->qstr($str); |
418: | } |
419: | |
420: | |
421: | |
422: | |
423: | |
424: | |
425: | public static function escape($str) { |
426: | $conn = DB::getConnect(); |
427: | return mysqli_real_escape_string($conn->_connectionID, $str); |
428: | } |
429: | |
430: | |
431: | |
432: | |
433: | |
434: | |
435: | public static function dbdate($dt) { |
436: | $conn = DB::getConnect(); |
437: | return $conn->DBDate($dt); |
438: | } |
439: | |
440: | |
441: | |
442: | |
443: | |
444: | |
445: | |
446: | final public function __get($name) { |
447: | return $this->fields[$name] ?? null; |
448: | } |
449: | |
450: | |
451: | |
452: | |
453: | |
454: | |
455: | |
456: | final public function __set($name, $value) { |
457: | $this->fields[$name] = $value; |
458: | } |
459: | |
460: | |
461: | |
462: | |
463: | |
464: | final public function getData() { |
465: | return $this->fields; |
466: | } |
467: | |
468: | |
469: | |
470: | |
471: | final public function setData($row) { |
472: | if (is_array($row)) { |
473: | $this->fields = array_merge($this->fields, $row); |
474: | } |
475: | |
476: | } |
477: | |
478: | |
479: | |
480: | |
481: | |
482: | final public function getKeyValue() { |
483: | $meta = $this->getMetadata(); |
484: | return $this->fields[$meta['keyfield']]; |
485: | } |
486: | |
487: | |
488: | |
489: | |
490: | |
491: | |
492: | public function save() { |
493: | |
494: | if ($this->beforeSave() === false) { |
495: | return; |
496: | }; |
497: | $conn = DB::getConnect(); |
498: | $meta = $this->getMetadata(); |
499: | $flist=$this->fields ; |
500: | unset($flist[$meta['keyfield']]); |
501: | if (($this->fields[$meta['keyfield']]?? 0) > 0) { |
502: | |
503: | $conn->AutoExecute($meta['table'], $flist, "UPDATE", "{$meta['keyfield']} = " . $this->fields[$meta['keyfield']]); |
504: | $this->afterSave(true); |
505: | } else { |
506: | $conn->AutoExecute($meta['table'], $flist, "INSERT"); |
507: | $this->fields[$meta['keyfield']] = $conn->Insert_ID(); |
508: | $this->afterSave(false); |
509: | } |
510: | } |
511: | |
512: | |
513: | |
514: | |
515: | |
516: | |
517: | protected function beforeSave() { |
518: | return true; |
519: | } |
520: | |
521: | |
522: | |
523: | |
524: | |
525: | |
526: | protected function afterSave($update) { |
527: | |
528: | } |
529: | |
530: | |
531: | |
532: | |
533: | |
534: | protected function afterLoad() { |
535: | |
536: | } |
537: | |
538: | |
539: | |
540: | |
541: | |
542: | |
543: | protected static function getConstraint() { |
544: | return ''; |
545: | } |
546: | |
547: | |
548: | } |
549: | |
550: | class ZDBException extends \Error |
551: | { |
552: | } |
553: | |