/application/models/mappers/MapperAbstract.php

https://bitbucket.org/klab_zhang_j/zf1example-usermanagement · PHP · 281 lines · 167 code · 24 blank · 90 comment · 23 complexity · ec98beddc38dda5f0cc017ab33d293b1 MD5 · raw file

  1. <?php
  2. /**
  3. * abstract mapper
  4. * this mapper based on db
  5. * @author Ken
  6. *
  7. */
  8. class Application_Model_Mapper_MapperAbstract
  9. {
  10. protected $_dbTableNamespace = 'Application_Model_DbTable';
  11. protected $_dbTableName;
  12. protected $_dbTableClass;
  13. protected $_modelClass;
  14. protected $_colsMap = array();
  15. protected $_dbTable;
  16. public function __construct()
  17. {
  18. //check necessary vars
  19. if (empty($this->_dbTableName)) {
  20. throw new RuntimeException(sprintf('need dbTableName in %s', get_class($this)));
  21. }
  22. }
  23. /**
  24. * load resource. mappers, dbTable, etc..
  25. * @param unknown $name
  26. * @param string $type
  27. * @throws RuntimeException
  28. */
  29. public function loadResource($name, $type = 'dbtable')
  30. {
  31. $name = ucfirst($name);
  32. $class = $this->_dbTableNamespace . '_' . $name;
  33. $resourceLoaders = Zend_Loader_Autoloader::getInstance()->getClassAutoloaders($class);
  34. foreach ($resourceLoaders as $loader) {
  35. return $loader->load($name, $type);
  36. }
  37. throw new RuntimeException('No loader for ' . $class);
  38. }
  39. /**
  40. *
  41. * @return Zend_Db_Table_Abstract
  42. */
  43. public function getDbTable()
  44. {
  45. if (null === $this->_dbTable) {
  46. $this->setDbTable($this->_dbTableName);
  47. }
  48. return $this->_dbTable;
  49. }
  50. /**
  51. * set dbTable
  52. * @param unknown $dbTable
  53. * @return Application_Model_Mapper_MapperAbstract
  54. */
  55. public function setDbTable($dbTable)
  56. {
  57. if (is_string($dbTable)) {
  58. $dbTable = $this->loadResource($dbTable);
  59. }
  60. $this->_dbTable = $dbTable;
  61. return $this;
  62. }
  63. /**
  64. * create a new model
  65. * @param array $data
  66. * @return Application_Model_ModelAbstract
  67. */
  68. public function createModel($data = array(), $from = null)
  69. {
  70. $model = new $this->_modelClass();
  71. if ('db' == $from && $data) {
  72. $this->_colsToModel($model, $data);
  73. } else {
  74. $model->populate($data);
  75. }
  76. return $model;
  77. }
  78. /**
  79. * create resultset as collection
  80. * @param array $resultset
  81. * @return array
  82. */
  83. public function createCollection($resultset)
  84. {
  85. $collection = new Application_Model_ModelCollection(array());
  86. foreach ($resultset as $data) {
  87. $collection[] = $this->createModel($data, 'db');
  88. }
  89. return $collection;
  90. }
  91. /**
  92. * mapping db col to model->property
  93. *
  94. * @param unknown_type $model
  95. * @param unknown_type $data
  96. */
  97. protected function _colsToModel($model, $data)
  98. {
  99. if (is_object($data) && is_callable(array($data, 'toArray'))) {
  100. $data = $data->toArray();
  101. }
  102. foreach ($this->_colsMap as $property => $col) {
  103. $callfunc = array($model, 'set' . $property);
  104. if (is_callable($callfunc)) {
  105. call_user_func($callfunc, isset($data[$col]) ? $data[$col] : null);
  106. } else {
  107. $model->$property = isset($data[$col]) ? $data[$col] : null;
  108. }
  109. }
  110. return $model;
  111. }
  112. /**
  113. * mapping model to db
  114. * @param unknown $data
  115. * @return multitype:unknown
  116. */
  117. protected function _modelToCols($data)
  118. {
  119. if (is_object($data) && is_callable(array($data, 'toArray'))) {
  120. $data = $data->toArray();
  121. }
  122. $result = array();
  123. foreach ($data as $property => $value) {
  124. if (isset($this->_colsMap[$property])) {
  125. $cols = $this->_colsMap[$property];
  126. $result[$cols] = $value;
  127. }
  128. }
  129. return $result;
  130. }
  131. /**
  132. *
  133. * Fetch row if primy key exists, otherwise create a row
  134. * @param array $data
  135. * @return Zend_Db_Table_Row_Abstract
  136. * @throws InvalidArgumentException
  137. */
  138. protected function _fetchRowOrCreate($data)
  139. {
  140. $row = $this->_fetchRow($data);
  141. if (null == $row) {
  142. $row = $this->getDbTable()->createRow();
  143. }
  144. return $row;
  145. }
  146. /**
  147. * fetch row from table
  148. *
  149. * @param array $data
  150. * @return Zend_Db_Table_Row_Abstract
  151. * @throws InvalidArgumentException
  152. */
  153. protected function _fetchRow($data)
  154. {
  155. $table = $this->getDbTable();
  156. $pk = $table->info('primary');
  157. if (!is_array($pk)) {
  158. $pk = (array) $pk;
  159. }
  160. $pkData = array();
  161. foreach ($pk as $fieldName) {
  162. if (array_key_exists($fieldName, $data)) {
  163. $pkData[] = $data[$fieldName];
  164. } elseif (!empty($pkData)) {
  165. throw new InvalidArgumentException("Could not find Primary Key part '$fieldName'");
  166. }
  167. }
  168. if (empty($pkData)) {
  169. return null;
  170. } else {
  171. $rowset = call_user_func_array(array($table , 'find'), $pkData);
  172. $row = $rowset->current();
  173. }
  174. return $row;
  175. }
  176. /**
  177. * Save model to db
  178. * @param Application_Model_ModelAbstract $model
  179. * @return Application_Model_Mapper_MapperAbstract
  180. */
  181. public function save(Application_Model_ModelAbstract $model)
  182. {
  183. $data = $this->_modelToCols($model);
  184. $row = $this->_fetchRowOrCreate($data);
  185. $row->setFromArray($data);
  186. $row->save();
  187. $this->_colsToModel($model, $row);//refresh data
  188. return $this;
  189. }
  190. /**
  191. * Find by PK
  192. * @param unknown $id
  193. * @return Ambigous <multitype:, Application_Model_ModelCollection, Application_Model_ModelAbstract>
  194. */
  195. public function find($id)
  196. {
  197. return $this->createCollection($this->getDbTable()->find($id));
  198. }
  199. /**
  200. * fetchAll record
  201. * @param string $select
  202. * @return Ambigous <multitype:, Application_Model_ModelCollection, Application_Model_ModelAbstract>
  203. */
  204. public function fetchAll($select = null)
  205. {
  206. $table = $this->getDbTable();
  207. return $this->createCollection($table->fetchAll($select));
  208. }
  209. /**
  210. * get SQL
  211. * @return Zend_Db_Table_Select
  212. */
  213. public function getSqlSelect()
  214. {
  215. return $this->getDbTable()->select();
  216. }
  217. /**
  218. * get db adapter
  219. * @return Zend_Db_Adapter_Abstract
  220. */
  221. public function getDbAdapter()
  222. {
  223. return $this->getDbTable()->getAdapter();
  224. }
  225. /**
  226. * magic call
  227. * handle:
  228. * findBy{PropertyName}
  229. * find{Resource}By{Model} => call {Resource}Mapper::findBy{Model}($model)
  230. * @param unknown $method
  231. * @param unknown $params
  232. * @throws RuntimeException
  233. * @return Ambigous <multitype:, Application_Model_ModelCollection, Application_Model_ModelAbstract>
  234. */
  235. public function __call($method, $params)
  236. {
  237. if (preg_match('/find([A-Za-z0-9_]+)By([A-Za-z0-9_]+)/', $method, $matches)) {
  238. $resourceName = $matches[1];
  239. $method = 'findBy' . $matches[2];
  240. $resource = $this->loadResource($resourceName, 'mappers');
  241. return call_user_func_array(array($resource, $method), $params);
  242. }
  243. $magicMethodFindBy = 'findBy';
  244. if (false !== ($p = stripos($method, $magicMethodFindBy))) {
  245. $col = lcfirst(substr($method, $p+strlen($magicMethodFindBy)));
  246. if (isset($this->_colsMap[$col])) {
  247. $col = $this->_colsMap[$col];
  248. }
  249. $param = $params[0];
  250. $op = is_array($param) ? ' IN (?)' : ' = ?';
  251. $select = $this->getSqlSelect();
  252. $select->where($col . $op, $param);
  253. return $this->fetchAll($select);
  254. }
  255. throw new RuntimeException(sprintf('Call undefined method %s::%s', get_class($this), $method));
  256. }
  257. }