Passed
Push — master ( cd6927...afac5a )
by 世昌
02:10
created

PrepareTrait::parepareWhereString()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 3
nop 2
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
namespace suda\orm\statement;
3
4
use ArrayObject;
5
use suda\orm\Binder;
6
use suda\orm\exception\SQLException;
7
8
/**
9
 * Trait PrepareTrait
10
 * @package suda\orm\statement
11
 */
12
trait PrepareTrait
13
{
14
15
    /**
16
     * 准备选择列
17
     *
18
     * @param string|array $reads
19
     * @param string $table
20
     * @return string
21
     */
22
    protected function prepareReadFields($reads, string $table = ''):string
23
    {
24
        if (is_string($reads)) {
25
            $fields = $reads;
26
        } else {
27
            $field = [];
28
            $prefix = strlen($table) ?"`{$table}`." :'';
29
            foreach ($reads as $want) {
30
                $field[] = $prefix."`$want`";
31
            }
32
            $fields = implode(',', $field);
33
        }
34
        return $fields;
35
    }
36
37
    /**
38
     * 准备条件列
39
     *
40
     * @param array $where
41
     * @return array
42
     * @throws SQLException
43
     */
44
    protected function parepareWhere(array $where)
45
    {
46
        $and = [];
47
        $binders = [];
48
        foreach ($where as $name => $value) {
49
            $_name = Binder::index($name);
50
            // in cause
51
            if ($value instanceof ArrayObject) {
52
                list($sql, $in_binder) = $this->prepareIn($name, $value);
53
                $and[] = $sql;
54
                $binders = array_merge($binders, $in_binder);
55
            } elseif (is_array($value)) {
56
                list($op, $val) = $value;
57
                $op = trim($op);
58
                $and[] = "`{$name}` {$op} :{$_name}";
59
                $binders[] = new Binder($_name, $val);
60
            } else {
61
                $and[] = "`{$name}`=:{$_name}";
62
                $binders[] = new Binder($_name, $value);
63
            }
64
        }
65
        return [implode(' AND ', $and), $binders];
66
    }
67
68
    /**
69
     * @param string $where
70
     * @param array $whereBinder
71
     * @return array
72
     * @throws SQLException
73
     */
74
    protected function prepareWhereString(string $where, array $whereBinder)
75
    {
76
        foreach ($whereBinder as $name => $value) {
77
            if (is_array($value) || $value instanceof ArrayObject) {
78
                list($inSQL, $binders) = $this->prepareInParameter($value, $name);
79
                $whereBinder = array_merge($whereBinder, $binders);
80
                $name = ltrim($name, ':');
81
                $where = str_replace(':'.$name, $inSQL, $where);
82
            }
83
        }
84
        return [$where, $whereBinder];
85
    }
86
87
88
    /**
89
     * 准备In
90
     *
91
     * @param string $name
92
     * @param ArrayObject|array $values
93
     * @return array
94
     * @throws SQLException
95
     */
96
    protected function prepareIn(string $name, $values)
97
    {
98
        list($inSQL, $binders) = $this->prepareInParameter($values, $name);
99
        $sql = $name.' IN ('.$inSQL.')';
100
        return [$sql,$binders];
101
    }
102
103
    /**
104
     * @param $values
105
     * @param string $name
106
     * @return array
107
     * @throws SQLException
108
     */
109
    protected function prepareInParameter($values, string $name)
110
    {
111
        if (count($values) <= 0) {
112
            throw new SQLException('on field '.$name.' value can\'t be empty array');
113
        }
114
        $names = [];
115
        $binders = [];
116
        foreach ($values as $value) {
117
            $_name = Binder::index($name);
118
            $binders[] = new Binder($_name, $value);
119
            $names[] = ':'.$_name;
120
        }
121
        return [implode(',', $names), $binders];
122
    }
123
124
    /**
125
     * 准备更新
126
     *
127
     * @param array $data
128
     * @return array
129
     */
130
    protected function prepareUpdateSet(array $data)
131
    {
132
        $binders = [];
133
        $sets = [];
134
        foreach ($data as $name => $value) {
135
            $_name = Binder::index($name);
136
            $binders[] = new Binder($_name, $value, $name);
137
            $sets[] = "`{$name}`=:{$_name}";
138
        }
139
        return [implode(',', $sets), $binders];
140
    }
141
142
    /**
143
     * 编译 ? 字符
144
     *
145
     * @param string $sql
146
     * @param array $parameter
147
     * @return array
148
     */
149
    protected function prepareQueryMark(string $sql, array $parameter)
150
    {
151
        $binders = [];
152
        $query = preg_replace_callback('/\?/', function ($match) use (&$binders, $parameter) {
153
            $index = count($binders);
154
            if (array_key_exists($index, $parameter)) {
155
                $name = Binder::index($index);
156
                if (is_array($parameter[$index]) || $parameter[$index] instanceof ArrayObject) {
157
                    list($inSQL, $inBinders) = $this->prepareInParameter($parameter[$index], $index);
158
                    $binders = array_merge($binders, $inBinders);
159
                    return $inSQL;
160
                } else {
161
                    $binder = new Binder($name, $parameter[$index]);
162
                    $binders[] = $binder;
163
                    return ':'.$binder->getName();
164
                }
165
            }
166
            return $match[0];
167
        }, $sql);
168
        return [$query, $binders];
169
    }
170
171
    /**
172
     * 合并绑定工具
173
     *
174
     * @param Binder[] $binder
175
     * @param array $parameter
176
     * @return Binder[]
177
     */
178
    protected function mergeBinder(array $binder, array $parameter)
179
    {
180
        foreach ($parameter as $key => $value) {
181
            if ($value instanceof Binder) {
182
                $binder[] = $value;
183
            } else {
184
                $binder[] = new Binder($key, $value);
185
            }
186
        }
187
        return $binder;
188
    }
189
}
190