colly_wyx
2018-06-13 e4d5467f055ece8cc9dfdc02dd836bcc187034a5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?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'];
            }
        }
    }
}