| <?php | 
| /** | 
|  * PhalApi_Model_NotORM 基于NotORM的Model基类 | 
|  * | 
|  * - 我们这里对ext_data使用json而不是序列化,是为了更容易阅读、理解、测试 | 
|  * - 可重写formatExtData() & parseExtData()重新定制针对序列化LOB的转换 | 
|  * - 具体子类需要实现getTableName($id)以提供对应的表名或者分表名 | 
|  * - 对于如何寻找表主键,我们将配置中全部的表(包括分表)对应的主键进行了装配,如果觉得有性能问题,可重写getTableKey($table);这是一个手动和自动的问题 | 
|  * | 
|  * @package     PhalApi\Model | 
|  * @license     http://www.phalapi.net/license | 
|  * @link        http://www.phalapi.net/ | 
|  * @author      dogstar <chanzonghuang@gmail.com> 2015-02-22 | 
|  */ | 
|   | 
| class PhalApi_Model_NotORM implements PhalApi_Model { | 
|   | 
|     protected static $tableKeys = array(); | 
|   | 
|     public function get($id, $fields = '*') { | 
|         $needFields = is_array($fields) ? implode(',', $fields) : $fields; | 
|         $notorm = $this->getORM($id); | 
|   | 
|         $table = $this->getTableName($id); | 
|         $rs = $notorm->select($needFields) | 
|             ->where($this->getTableKey($table), $id)->fetch(); | 
|   | 
|         $this->parseExtData($rs); | 
|   | 
|         return $rs; | 
|     } | 
|   | 
|     public function insert($data, $id = NULL) { | 
|         $this->formatExtData($data); | 
|   | 
|         $notorm = $this->getORM($id); | 
|         $notorm->insert($data); | 
|   | 
|         return $notorm->insert_id(); | 
|     } | 
|   | 
|     public function update($id, $data) { | 
|         $this->formatExtData($data); | 
|   | 
|         $notorm = $this->getORM($id); | 
|   | 
|         $table = $this->getTableName($id); | 
|         return $notorm->where($this->getTableKey($table), $id)->update($data); | 
|     } | 
|   | 
|     public function delete($id) { | 
|         $notorm = $this->getORM($id); | 
|   | 
|         $table = $this->getTableName($id); | 
|         return $notorm->where($this->getTableKey($table), $id)->delete(); | 
|     } | 
|   | 
|     /** | 
|      * 对LOB的ext_data字段进行格式化(序列化) | 
|      */ | 
|     protected function formatExtData(&$data) { | 
|         if (isset($data['ext_data'])) { | 
|             $data['ext_data'] = json_encode($data['ext_data']); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 对LOB的ext_data字段进行解析(反序列化) | 
|      */ | 
|     protected function parseExtData(&$data) { | 
|         if (isset($data['ext_data'])) { | 
|             $data['ext_data'] = json_decode($data['ext_data'], true); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 根据主键值返回对应的表名,注意分表的情况 | 
|      *  | 
|      * 默认表名为:[表前缀] + 全部小写的匹配表名 | 
|      * | 
|      * 在以下场景下,需要重写此方法以指定表名 | 
|      * + 1. 自动匹配的表名与实际表名不符 | 
|      * + 2. 存在分表  | 
|      * + 3. Model类名不含有Model_ | 
|      */ | 
|     protected function getTableName($id) { | 
|         $className = get_class($this); | 
|         $pos = strpos($className, 'Model'); | 
|   | 
|         $tableName = $pos !== FALSE ? substr($className, $pos + 6) : $className; | 
|         return strtolower($tableName); | 
|     } | 
|   | 
|     /** | 
|      * 根据表名获取主键名 | 
|      * | 
|      * - 考虑到配置中的表主键不一定是id,所以这里将默认自动装配数据库配置并匹配对应的主键名 | 
|      * - 如果不希望因自动匹配所带来的性能问题,可以在每个实现子类手工返回对应的主键名 | 
|      * - 注意分表的情况 | 
|      *  | 
|      * @param string $table 表名/分表名 | 
|      * @return string 主键名 | 
|      */ | 
|     protected function getTableKey($table) { | 
|         if (empty(static::$tableKeys)) { | 
|             $this->loadTableKeys(); | 
|         } | 
|   | 
|         return isset(static::$tableKeys[$table]) ? static::$tableKeys[$table] : static::$tableKeys['__default__']; | 
|     } | 
|   | 
|     /** | 
|      * 快速获取ORM实例,注意每次获取都是新的实例 | 
|      * @param string/int $id | 
|      * @return NotORM_Result | 
|      */ | 
|     protected function getORM($id = NULL) { | 
|         $table = $this->getTableName($id); | 
|         return DI()->notorm->$table; | 
|     } | 
|   | 
|     protected function loadTableKeys() { | 
|         $tables = DI()->config->get('dbs.tables'); | 
|         if (empty($tables)) { | 
|             throw new PhalApi_Exception_InternalServerError(T('dbs.tables should not be empty')); | 
|         } | 
|   | 
|         foreach ($tables as $tableName => $tableConfig) { | 
|             if (isset($tableConfig['start']) && isset($tableConfig['end'])) { | 
|                 for ($i = $tableConfig['start']; $i <= $tableConfig['end']; $i ++) { | 
|                     static::$tableKeys[$tableName . '_' . $i] = $tableConfig['key']; | 
|                 } | 
|             } else { | 
|                 static::$tableKeys[$tableName] = $tableConfig['key']; | 
|             } | 
|         } | 
|     } | 
| } |