Passed
Push — master ( f0d9c0...7714bf )
by 世昌
03:10
created

DataAccess::run()   A

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\orm;
3
4
use ReflectionClass;
5
use ReflectionProperty;
6
use suda\orm\DataSource;
7
use suda\orm\TableAccess;
8
use suda\orm\statement\Statement;
9
use suda\orm\struct\ReadStatement;
10
use suda\orm\middleware\Middleware;
11
use suda\orm\struct\QueryStatement;
12
use suda\orm\struct\WriteStatement;
13
use suda\orm\middleware\NullMiddleware;
14
use suda\orm\struct\TableStructBuilder;
15
use suda\orm\struct\TableStructMiddleware;
16
use suda\orm\struct\TableClassStructBuilder;
17
use suda\orm\struct\TableStructAwareInterface;
18
use suda\orm\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 \suda\orm\DataSource $source
45
     * @param Middleware|null $middleware
46
     */
47
    public function __construct(string $object, DataSource $source, ?Middleware $middleware = null)
48
    {
49
        $this->type = $object;
50
        $struct = $this->createStruct($object);
51
        $middleware = $middleware ?? $this->createMiddleware($object, $struct);
52
        $this->access = new TableAccess($struct, $source, $middleware);
53
    }
54
55
    /**
56
     * 读取数据
57
     *
58
     * @param array|string $fields
59
     * @return \suda\orm\struct\ReadStatement
60
     */
61
    public function read(...$fields): ReadStatement
62
    {
63
        return $this->access->read(...$fields)->wantType($this->type);
64
    }
65
    
66
    /**
67
     * 写数据
68
     *
69
     * @param array|object|string $object
70
     * @return \suda\orm\struct\WriteStatement
71
     */
72
    public function write($object): WriteStatement
73
    {
74
        if (\is_object($object)) {
75
            $object = $this->createDataFromObject($object);
76
        }
77
        return $this->access->write($object);
78
    }
79
80
    /**
81
     * 删
82
     *
83
     * @param string|array $where
84
     * @param array $whereParameter
85
     * @return \suda\orm\struct\WriteStatement
86
     */
87
    public function delete($where = null, ...$whereParameter):WriteStatement
88
    {
89
        if ($where !== null) {
90
            return (new WriteStatement($this))->delete()->where($where, ...$whereParameter);
0 ignored issues
show
Bug introduced by
$this of type suda\orm\DataAccess is incompatible with the type suda\orm\TableAccess expected by parameter $access of suda\orm\struct\WriteStatement::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

90
            return (new WriteStatement(/** @scrutinizer ignore-type */ $this))->delete()->where($where, ...$whereParameter);
Loading history...
91
        }
92
        return (new WriteStatement($this))->delete();
93
    }
94
95
    /**
96
     * 统计计数
97
     *
98
     * @param string|array|object $where
99
     * @param array $whereBinder
100
     * @return integer
101
     */
102
    public function count($where, array $whereBinder = []):int
103
    {
104
        if (\is_object($where)) {
105
            $where = $this->createDataFromObject($where);
106
        }
107
        $fields = $this->access->getStruct()->getFields()->all();
108
        $field = \array_shift($fields);
109
        $total = $this->access->read([$field->getName()])->where($where, $whereBinder);
110
        $data = $this->access->query('SELECT count(*) as `count` from ('.$total.') as total', $total->getBinder())->one();
111
        return intval($data['count']);
112
    }
113
114
    /**
115
     * 查询语句
116
     *
117
     * @param string $query
118
     * @param mixed ...$parameter
119
     * @return QueryStatement
120
     */
121
    public function query(string $query, ...$parameter):QueryStatement
122
    {
123
        return $this->access->query($query, ...$parameter);
124
    }
125
126
127
    /**
128
     * 运行SQL语句
129
     *
130
     * @param Statement $statement
131
     * @return mixed
132
     */
133
    public function run(Statement $statement)
134
    {
135
        return $this->access->run($statement);
136
    }
137
    
138
    /**
139
     * 获取最后一次插入的主键ID(用于自增值
140
     *
141
     * @param string $name
142
     * @return string 则获取失败,整数则获取成功
143
     */
144
    public function lastInsertId(string $name = null):string
145
    {
146
        return $this->access->lastInsertId($name);
147
    }
148
149
    /**
150
     * 事务系列,开启事务
151
     *
152
     * @return void
153
     */
154
    public function beginTransaction()
155
    {
156
        $this->access->beginTransaction();
157
    }
158
159
    /**
160
     * 事务系列,提交事务
161
     *
162
     * @return void
163
     */
164
    public function commit()
165
    {
166
        $this->access->commit();
167
    }
168
169
    /**
170
     * 事务系列,撤销事务
171
     *
172
     * @return void
173
     */
174
    public function rollBack()
175
    {
176
        $this->access->rollBack();
177
    }
178
179
    /**
180
     * 创建数据
181
     *
182
     * @param object $object
183
     * @return array
184
     */
185
    protected function createDataFromObject($object)
186
    {
187
        if (\method_exists($object, '__get')) {
188
            return $this->createDataViaMagicGet($object);
189
        }
190
        return $this->createDataViaReflection($object);
191
    }
192
193
    /**
194
     * 使用魔术方法获取值
195
     *
196
     * @param object $object
197
     * @return array
198
     */
199
    protected function createDataViaMagicGet($object)
200
    {
201
        $fields = $this->access->getStruct()->getFields();
202
        $data = [];
203
        $isset = \method_exists($object, '__isset');
204
        if ($isset) {
205
            foreach ($fields as $name => $value) {
206
                if ($object->__isset($name)) {
207
                    $dataField = $this->access->getMiddleware()->inputName($name);
208
                    $data[$dataField] = $object->__get($name);
209
                }
210
            }
211
        } else {
212
            foreach ($fields as $name => $value) {
213
                $dataField = $this->access->getMiddleware()->inputName($name);
214
                $data[$dataField] = $object->__get($name);
215
            }
216
        }
217
        return $data;
218
    }
219
220
    /**
221
     * 使用反射方法获取值
222
     *
223
     * @param object $object
224
     * @return array
225
     */
226
    protected function createDataViaReflection($object)
227
    {
228
        $reflection = new ReflectionClass($object);
229
        $data = [];
230
        foreach ($reflection->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PRIVATE) as $property) {
231
            if (TableStructBuilder::isTableField($property)) {
232
                $property->setAccessible(true);
233
                $value = $property->getValue($object);
234
                if ($value !== null) {
235
                    $dataField = $this->access->getMiddleware()->inputName($property->getName());
236
                    $data[$dataField] = $value;
237
                }
238
            }
239
        }
240
        return $data;
241
    }
242
243
    /**
244
     * 创建表结构
245
     *
246
     * @param string $object
247
     * @return TableStruct
248
     */
249
    public static function createStruct(string $object)
250
    {
251
        if (is_subclass_of($object, TableStructAwareInterface::class)) {
252
            return $object::getTableStruct();
253
        }
254
        return (new TableClassStructBuilder($object))->createStruct();
255
    }
256
257
    /**
258
     * 创建中间件
259
     *
260
     * @param string $object
261
     * @param TableStruct $struct
262
     * @return Middleware
263
     */
264
    public static function createMiddleware(string $object, TableStruct $struct)
265
    {
266
        if (is_subclass_of($object, MiddlewareAwareInterface::class)) {
267
            return $object::getMiddleware($struct);
268
        }
269
        return static::createDefaultMiddleware($object, $struct);
270
    }
271
272
    /**
273
     * 创建默认中间件
274
     *
275
     * @param string $object
276
     * @param TableStruct $struct
277
     * @return Middleware
278
     */
279
    protected static function createDefaultMiddleware(string $object, TableStruct $struct)
280
    {
281
        $reflectObject = new ReflectionClass($object);
282
        $classDoc = is_string($reflectObject->getDocComment())?$reflectObject->getDocComment():'';
283
        if (\preg_match('/@field-(serialize|json)\s+(\w+)/i', $classDoc, $matchs)) {
284
            return new TableStructMiddleware($object, $struct);
285
        }
286
        return new NullMiddleware;
287
    }
288
289
    /**
290
     * 获取表结构
291
     *
292
     * @return \suda\orm\TableStruct
293
     */
294
    public function getStruct():TableStruct
295
    {
296
        return $this->access->getStruct();
297
    }
298
299
    /**
300
     * 获取表名
301
     *
302
     * @return string
303
     */
304
    public function getName():string
305
    {
306
        return $this->access->getName();
307
    }
308
}
309