Overview

Namespaces

  • Ark
    • Database

Classes

  • Ark\Database\Connection
  • Ark\Database\Model
  • Ark\Database\ModelFactory
  • Ark\Database\QueryBuilder

Interfaces

  • Ark\Database\Exception
  • Overview
  • Namespace
  • Class
  1: <?php
  2: /**
  3:  * ark.database
  4:  * @copyright 2015 Liu Dong <ddliuhb@gmail.com>
  5:  * @license MIT
  6:  */
  7: 
  8: namespace Ark\Database;
  9: 
 10: /**
 11:  * Model factory
 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:      * PK getter
 47:      */
 48:     public function getPK(){
 49:         return $this->pk;
 50:     }
 51:     
 52:     /**
 53:      * Table getter
 54:      */
 55:     public function getTable(){
 56:         return $this->table;
 57:     }
 58:     
 59:     /**
 60:      * @todo fetch related data together
 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:             //if(strpos($column, '.')
 73:         }
 74:         $this->with = null;
 75:     }
 76:     
 77:     /**
 78:      * Map array to model
 79:      * 
 80:      * @param array $row
 81:      * @return \Ark\Database\Model
 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:      * Map data rows to model array
 92:      * 
 93:      * @param array $rows
 94:      * @return array
 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:      * Create a fresh model from array
107:      * 
108:      * @param array $row
109:      * @return \Ark\Database\Model
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:      * Build PK condition(multiple pk is also supported)
121:      * 
122:      * @param string|array $pk
123:      * @param mixed $_data
124:      * @return array
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:      * Count with conditions
148:      * 
149:      * @param string|array $conditions
150:      * @param array $params
151:      * @return integer
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:      * Count by key
159:      * 
160:      * @param string $key
161:      * @param mixed $value
162:      * @return integer
163:      */
164:     public function countBy($key, $value){
165:         return $this->count($key.'=:key', array(':key' => $value));
166:     }
167:     
168:     /**
169:      * Find by PK
170:      * @param int $id
171:      */
172:     public function find($pk){
173:         return $this->findByPK($pk);
174:     }
175:     
176:     /**
177:      * Find all
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:      * Find one model with conditions
190:      * 
191:      * @param string|array $conditions
192:      * @param array $params
193:      * @return \Ark\Database\Model Or false on failure
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:      * Find one model by key
206:      * 
207:      * @param string $key
208:      * @param mixed $value
209:      * @return \Ark\Database\Model Or false on failure
210:      */
211:     public function findOneBy($key, $value){
212:         return $this->findOne($key.'=:key', array(':key' => $value));
213:     }
214:     
215:     /**
216:      * Find one model by primary key
217:      * 
218:      * @param string|array $pk
219:      * @return \Ark\Database\Model Or false on failure
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:      * Find many models with conditions
228:      * 
229:      * @param string|array $conditions
230:      * @param array $params
231:      * @param string|array $orderBy
232:      * @param int $limit
233:      * @param int $offset
234:      * @return array Or false on failure
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:      * Find many models with by key
252:      * 
253:      * @param string $key
254:      * @param mixed $value
255:      * @param string|array $orderBy
256:      * @param int $limit
257:      * @param int $offset
258:      * @return array Or false on failure
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:      * Update table with condition
266:      * 
267:      * @param array $values
268:      * @param string|array $conditions
269:      * @param array $params
270:      * @return int|boolean
271:      */
272:     public function update($values, $conditions = '', $params = array()){
273:         return $this->db->builder()->update($this->table, $values, $conditions, $params);
274:     }
275:     
276:     /**
277:      * Update table by key
278:      * 
279:      * @param string $key
280:      * @param mixed $value
281:      * @param array $values
282:      * @return int|boolean
283:      */
284:     public function updateBy($key, $value, $values){
285:         return $this->update($values, $key.'=:key', array(':key' => $value));
286:     }
287:     
288:     /**
289:      * Update table by primary key
290:      * @param string|array $pk
291:      * @param array $values
292:      * @return int|boolean
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:      * Insert
301:      * 
302:      * @param array $values
303:      * @return int|boolean
304:      */
305:     public function insert($values){
306:         return $this->db->builder()->insert($this->table, $values);
307:     }
308:     
309:     /**
310:      * Delete with condition
311:      * 
312:      * @param string|array $conditioins
313:      * @param array $params
314:      * @return int|boolean
315:      */
316:     public function delete($conditions = '', $params = array()){
317:         return $this->db->builder()->delete($this->table, $conditions, $params);
318:     }
319:     
320:     /**
321:      * Delete by key
322:      * 
323:      * @param string $key
324:      * @param mixed $value
325:      * @return int|boolean
326:      */
327:     public function deleteBy($key, $value){
328:         return $this->delete($key.'=:key', array(':key' => $value));
329:     }
330:     
331:     /**
332:      * Delete by primary key
333:      * 
334:      * @param string|array $pk
335:      * @return int|boolean
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:      * Override __call magic method to provide many helper methods
344:      * 
345:      * @param string $name
346:      * @param array $arguments
347:      * @return mixed
348:      */
349:     public function __call($name, $arguments){
350:         //findOneByXXX/findManyByXXX
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: 
API documentation generated by ApiGen