Passed
Push — master ( c79051...5600d0 )
by 世昌
02:50 queued 11s
created

DataAccess::createTableName()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
namespace suda\orm;
3
4
use function array_shift;
5
use function is_object;
6
use function method_exists;
7
use function preg_match;
8
use ReflectionClass;
9
use ReflectionException;
10
use ReflectionProperty;
11
use suda\orm\statement\Statement;
12
use suda\orm\struct\ReadStatement;
13
use suda\orm\middleware\Middleware;
14
use suda\orm\struct\QueryStatement;
15
use suda\orm\struct\WriteStatement;
16
use suda\orm\middleware\NullMiddleware;
17
use suda\orm\struct\TableStructBuilder;
18
use suda\orm\struct\TableStructMiddleware;
19
use suda\orm\struct\TableClassStructBuilder;
20
use suda\orm\struct\TableStructAwareInterface;
21
use suda\orm\middleware\MiddlewareAwareInterface;
22
23
/**
24
 * 数据访问
25
 */
26
class DataAccess
27
{
28
29
    /**
30
     * 数据源
31
     *
32
     * @var TableAccess
33
     */
34
    protected $access;
35
36
    /**
37
     * 数据类型
38
     *
39
     * @var string
40
     */
41
    protected $type;
42
43
    /**
44
     * 创建对数据的操作
45
     *
46
     * @param string $object
47
     * @param DataSource $source
48
     * @param Middleware|null $middleware
49
     * @throws ReflectionException
50
     */
51
    public function __construct(string $object, DataSource $source, ?Middleware $middleware = null)
52
    {
53
        $this->type = $object;
54
        $struct = $this->createStruct($object);
55
        $middleware = $middleware ?? $this->createMiddleware($object, $struct);
56
        $this->access = new TableAccess($struct, $source, $middleware);
57
    }
58
59
    /**
60
     * 读取数据
61
     *
62
     * @param array|string $fields
63
     * @return ReadStatement
64
     */
65
    public function read(...$fields): ReadStatement
66
    {
67
        return $this->access->read(...$fields)->wantType($this->type);
68
    }
69
70
    /**
71
     * 写数据
72
     *
73
     * @param array|object|string $object
74
     * @return WriteStatement
75
     * @throws ReflectionException
76
     * @throws exception\SQLException
77
     */
78
    public function write($object): WriteStatement
79
    {
80
        if (is_object($object)) {
81
            $object = $this->createDataFromObject($object);
82
        }
83
        return $this->access->write($object);
84
    }
85
86
    /**
87
     * 删
88
     *
89
     * @param string|array $where
90
     * @param array $whereParameter
91
     * @return WriteStatement
92
     * @throws exception\SQLException
93
     */
94
    public function delete($where = null, ...$whereParameter):WriteStatement
95
    {
96
        if ($where !== null) {
97
            return $this->access->delete($where, ...$whereParameter);
98
        }
99
        return $this->access->delete();
100
    }
101
102
    /**
103
     * 统计计数
104
     *
105
     * @param string|array|object $where
106
     * @param array $whereBinder
107
     * @return integer
108
     * @throws ReflectionException
109
     * @throws exception\SQLException
110
     */
111
    public function count($where, array $whereBinder = []):int
112
    {
113
        if (is_object($where)) {
114
            $where = $this->createDataFromObject($where);
115
        }
116
        $fields = $this->access->getStruct()->getFields()->all();
117
        $field = array_shift($fields);
118
        $total = $this->access->read([$field->getName()])->where($where, $whereBinder);
119
        $data = $this->access->query(
120
            sprintf("SELECT count(*) as `count` from (%s) as total", $total),
121
            $total->getBinder()
122
        )->one();
123
        return intval($data['count']);
124
    }
125
126
    /**
127
     * 查询语句
128
     *
129
     * @param string $query
130
     * @param mixed ...$parameter
131
     * @return QueryStatement
132
     */
133
    public function query(string $query, ...$parameter):QueryStatement
134
    {
135
        return $this->access->query($query, ...$parameter);
136
    }
137
138
139
    /**
140
     * 运行SQL语句
141
     *
142
     * @param Statement $statement
143
     * @return mixed
144
     * @throws exception\SQLException
145
     */
146
    public function run(Statement $statement)
147
    {
148
        return $this->access->run($statement);
149
    }
150
    
151
    /**
152
     * 获取最后一次插入的主键ID(用于自增值
153
     *
154
     * @param string $name
155
     * @return string 则获取失败,整数则获取成功
156
     */
157
    public function lastInsertId(string $name = null):string
158
    {
159
        return $this->access->lastInsertId($name);
160
    }
161
162
    /**
163
     * 事务系列,开启事务
164
     *
165
     * @return void
166
     */
167
    public function beginTransaction()
168
    {
169
        $this->access->beginTransaction();
170
    }
171
172
    /**
173
     * 事务系列,提交事务
174
     *
175
     * @return void
176
     */
177
    public function commit()
178
    {
179
        $this->access->commit();
180
    }
181
182
    /**
183
     * 事务系列,撤销事务
184
     *
185
     * @return void
186
     */
187
    public function rollBack()
188
    {
189
        $this->access->rollBack();
190
    }
191
192
    /**
193
     * 创建数据
194
     *
195
     * @param object $object
196
     * @return array
197
     * @throws ReflectionException
198
     */
199
    protected function createDataFromObject($object)
200
    {
201
        if (method_exists($object, '__get')) {
202
            return $this->createDataViaMagicGet($object);
203
        }
204
        return $this->createDataViaReflection($object);
205
    }
206
207
    /**
208
     * 使用魔术方法获取值
209
     *
210
     * @param object $object
211
     * @return array
212
     */
213
    protected function createDataViaMagicGet($object)
214
    {
215
        $fields = $this->access->getStruct()->getFields();
216
        $data = [];
217
        $isset = method_exists($object, '__isset');
218
        if ($isset) {
219
            foreach ($fields as $name => $value) {
220
                if ($object->__isset($name)) {
221
                    $dataField = $this->access->getMiddleware()->inputName($name);
222
                    $data[$dataField] = $object->__get($name);
223
                }
224
            }
225
        } else {
226
            foreach ($fields as $name => $value) {
227
                $dataField = $this->access->getMiddleware()->inputName($name);
228
                $data[$dataField] = $object->__get($name);
229
            }
230
        }
231
        return $data;
232
    }
233
234
    /**
235
     * 使用反射方法获取值
236
     *
237
     * @param object $object
238
     * @return array
239
     * @throws ReflectionException
240
     */
241
    protected function createDataViaReflection($object)
242
    {
243
        $reflection = new ReflectionClass($object);
244
        $data = [];
245
        foreach ($reflection->getProperties(
246
            ReflectionProperty::IS_PUBLIC
247
            | ReflectionProperty::IS_PROTECTED
248
            | ReflectionProperty::IS_PRIVATE
249
        ) as $property) {
250
            if (TableStructBuilder::isTableField($property)) {
251
                $property->setAccessible(true);
252
                $value = $property->getValue($object);
253
                if ($value !== null) {
254
                    $dataField = $this->access->getMiddleware()->inputName($property->getName());
255
                    $data[$dataField] = $value;
256
                }
257
            }
258
        }
259
        return $data;
260
    }
261
262
    /**
263
     * 创建表结构
264
     *
265
     * @param string $object
266
     * @return TableStruct
267
     * @throws ReflectionException
268
     */
269
    public static function createStruct(string $object)
270
    {
271
        if (is_subclass_of($object, TableStructAwareInterface::class)) {
272
            $struct = new TableStruct(static::createTableName($object));
273
            return forward_static_call([$object, 'createTableStruct'], $struct);
274
        }
275
        return (new TableClassStructBuilder($object))->createStruct();
276
    }
277
278
279
    /**
280
     * @param string $object
281
     * @return string
282
     */
283
    public static function createTableName(string $object)
284
    {
285
        $pos = strrpos($object, '\\');
286
        if ($pos !== false && $pos >= 0) {
287
            $object = substr($object, $pos + 1);
288
        }
289
        return TableStructBuilder::createName($object);
290
    }
291
292
    /**
293
     * 创建中间件
294
     *
295
     * @param string $object
296
     * @param TableStruct $struct
297
     * @return Middleware
298
     * @throws ReflectionException
299
     */
300
    public static function createMiddleware(string $object, TableStruct $struct)
301
    {
302
        if (is_subclass_of($object, MiddlewareAwareInterface::class)) {
303
            return forward_static_call([$object, 'getMiddleware']);
304
        }
305
        return static::createDefaultMiddleware($object, $struct);
306
    }
307
308
    /**
309
     * 创建默认中间件
310
     *
311
     * @param string $object
312
     * @param TableStruct $struct
313
     * @return Middleware
314
     * @throws ReflectionException
315
     */
316
    protected static function createDefaultMiddleware(string $object, TableStruct $struct)
317
    {
318
        $reflectObject = new ReflectionClass($object);
319
        $classDoc = is_string($reflectObject->getDocComment())?$reflectObject->getDocComment():'';
320
        if (preg_match('/@field-(serialize|json)\s+(\w+)/i', $classDoc, $matchs)) {
321
            return new TableStructMiddleware($object, $struct);
322
        }
323
        return new NullMiddleware;
324
    }
325
326
    /**
327
     * 获取表结构
328
     *
329
     * @return TableStruct
330
     */
331
    public function getStruct():TableStruct
332
    {
333
        return $this->access->getStruct();
334
    }
335
336
    /**
337
     * 获取表名
338
     *
339
     * @return string
340
     */
341
    public function getName():string
342
    {
343
        return $this->access->getName();
344
    }
345
}
346