1: <?php
2: 3: 4: 5: 6:
7:
8: namespace Ark\Database;
9:
10: 11: 12:
13: class ModelFactory
14: {
15: protected $db;
16: protected $modelClass;
17: protected $table;
18: protected $pk;
19: protected $with;
20:
21: public function __construct($db, $model, $pk = null){
22: $this->db = $db;
23: if($model[0] === '@'){
24: $this->modelClass = '\Ark\Database\Model';
25: $this->table = substr($model, 1);
26: }
27: else{
28: $this->modelClass = $model;
29: if(null !== $model::getConfig('table')){
30: $this->table = $model::getConfig('table');
31: }
32: else{
33: $this->table = $model::entityNameToDBName($model);
34: }
35: }
36: if(null !== $pk){
37: $this->pk = $pk;
38: }
39: else{
40: $class = $this->modelClass;
41: $this->pk = $class::getConfig('pk');
42: }
43: }
44:
45: 46: 47:
48: public function getPK(){
49: return $this->pk;
50: }
51:
52: 53: 54:
55: public function getTable(){
56: return $this->table;
57: }
58:
59: 60: 61:
62: public function with($with){
63: $this->with = $with;
64:
65: return $this;
66: }
67:
68: public function buildWith(){
69: $with = $this->with;
70: $columns = explode(',', $with);
71: foreach($columns as $column){
72:
73: }
74: $this->with = null;
75: }
76:
77: 78: 79: 80: 81: 82:
83: public function map($row){
84: $class = $this->modelClass;
85: $model = new $class($this->db, $row, false);
86: $model->setAttribute('table', $this->table)->setAttribute('pk', $this->pk);
87: return $model;
88: }
89:
90: 91: 92: 93: 94: 95:
96: public function mapModels($rows){
97: $rst = array();
98: foreach($rows as $row){
99: $rst[] = $this->map($row);
100: }
101:
102: return $rst;
103: }
104:
105: 106: 107: 108: 109: 110:
111: public function create($row = array()){
112: $class = $this->modelClass;
113: $model = new $class($this->db, $row);
114: $model->setAttribute('table', $this->table)->setAttribute('pk', $this->pk);
115:
116: return $model;
117: }
118:
119: 120: 121: 122: 123: 124: 125:
126: protected function buildPKConditions($pk, $_data){
127: if(is_string($pk)){
128: $pks = array($pk);
129: if(!is_array($_data)){
130: $_data = array($pk => $_data);
131: }
132: }
133: else{
134: $pks = $pk;
135: }
136: $params = array();
137: foreach($pks as $k => $pk){
138: $pks[$k] = $pk.'=:pk'.$k;
139: $params[':pk'.$k] = $_data[$pk];
140: }
141: array_unshift($pks, 'AND');
142:
143: return array($pks, $params);
144: }
145:
146: 147: 148: 149: 150: 151: 152:
153: public function count($conditions = '', $params = array()){
154: return $this->db->builder()->select('COUNT(*)')->from($this->table)->where($conditions, $params)->queryValue();
155: }
156:
157: 158: 159: 160: 161: 162: 163:
164: public function countBy($key, $value){
165: return $this->count($key.'=:key', array(':key' => $value));
166: }
167:
168: 169: 170: 171:
172: public function find($pk){
173: return $this->findByPK($pk);
174: }
175:
176: 177: 178:
179: public function findAll(){
180: $rows = $this->db->builder()->select()->from($this->table)->queryAll();
181: if(false === $rows){
182: return $rows;
183: }
184:
185: return $this->mapModels($rows);
186: }
187:
188: 189: 190: 191: 192: 193: 194:
195: public function findOne($conditions, $params = array()){
196: $row = $this->db->builder()->select()->from($this->table)->where($conditions, $params)->limit(1)->queryRow();
197: if(false === $row){
198: return false;
199: }
200:
201: return $this->map($row);
202: }
203:
204: 205: 206: 207: 208: 209: 210:
211: public function findOneBy($key, $value){
212: return $this->findOne($key.'=:key', array(':key' => $value));
213: }
214:
215: 216: 217: 218: 219: 220:
221: public function findByPK($pk){
222: $pkConditions = $this->buildPKConditions($this->pk, $pk);
223: return $this->findOne($pkConditions[0], $pkConditions[1]);
224: }
225:
226: 227: 228: 229: 230: 231: 232: 233: 234: 235:
236: public function findMany($conditions = '', $params = array(), $orderBy = null, $limit = null, $offset = null){
237: $cmd = $this->db->builder()->select()->from($this->table)->where($conditions, $params);
238: if($orderBy){
239: $cmd->orderBy($orderBy);
240: }
241: $rows = $cmd->limit($limit, $offset)->queryAll();
242: if(false === $rows){
243: return false;
244: }
245: else{
246: return $this->mapModels($rows);
247: }
248: }
249:
250: 251: 252: 253: 254: 255: 256: 257: 258: 259:
260: public function findManyBy($key, $value, $orderBy = null, $limit = null, $offset = null){
261: return $this->findMany($key.'=:key', array(':key' => $value), $orderBy, $limit, $offset);
262: }
263:
264: 265: 266: 267: 268: 269: 270: 271:
272: public function update($values, $conditions = '', $params = array()){
273: return $this->db->builder()->update($this->table, $values, $conditions, $params);
274: }
275:
276: 277: 278: 279: 280: 281: 282: 283:
284: public function updateBy($key, $value, $values){
285: return $this->update($values, $key.'=:key', array(':key' => $value));
286: }
287:
288: 289: 290: 291: 292: 293:
294: public function updateByPK($pk, $values){
295: $pkConditions = $this->buildPKConditions($this->pk, $pk);
296: return $this->update($values, $pkConditions[0], $pkConditions[1]);
297: }
298:
299: 300: 301: 302: 303: 304:
305: public function insert($values){
306: return $this->db->builder()->insert($this->table, $values);
307: }
308:
309: 310: 311: 312: 313: 314: 315:
316: public function delete($conditions = '', $params = array()){
317: return $this->db->builder()->delete($this->table, $conditions, $params);
318: }
319:
320: 321: 322: 323: 324: 325: 326:
327: public function deleteBy($key, $value){
328: return $this->delete($key.'=:key', array(':key' => $value));
329: }
330:
331: 332: 333: 334: 335: 336:
337: public function deleteByPK($pk){
338: $pkConditions = $this->buildPKConditions($this->pk, $pk);
339: return $this->delete($pkConditions[0], $pkConditions[1]);
340: }
341:
342: 343: 344: 345: 346: 347: 348:
349: public function __call($name, $arguments){
350:
351: if(preg_match('#^find(One|Many)By(.+)$#', $name, $matches)){
352: $one = $matches[1] === 'One';
353: $findByKey = Model::entityNameToDBName($matches[2]);
354: array_unshift($arguments, $findByKey);
355: if($one){
356: return call_user_func_array(array($this, 'findOneBy'), $arguments);
357: }
358: else{
359: return call_user_func_array(array($this, 'findManyBy'), $arguments);
360: }
361: }
362: elseif(preg_match('#^(update|delete|count)By(.+)$#', $name, $matches)){
363: $action = $matches[1];
364: $actionByKey = Model::entityNameToDBName($matches[2]);
365: array_unshift($arguments, $actionByKey);
366: return call_user_func_array(array($this, $action.'By'), $arguments);
367: }
368: else{
369: throw new Exception(sprintf('Helper method "%s" does not exist', $name));
370: }
371: }
372: }
373: