DataAccess::read()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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