This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace PhpBoot\DB\impls; |
||
4 | use PhpBoot\DB\DB; |
||
5 | use PhpBoot\DB\Exceptions\DBException; |
||
6 | use PhpBoot\DB\NestedStringCut; |
||
7 | use PhpBoot\DB\Raw; |
||
8 | use PhpBoot\DB\rules\basic\BasicRule; |
||
9 | use PhpBoot\DB\Context; |
||
10 | |||
11 | class ExecResult{ |
||
12 | 28 | public function __construct($success, $pdo, $st){ |
|
13 | 28 | $this->pdo = $pdo; |
|
14 | 28 | $this->st = $st; |
|
15 | 28 | $this->success = $success; |
|
16 | 28 | $this->rows = $this->st->rowCount(); |
|
17 | 28 | } |
|
18 | 1 | public function lastInsertId($name=null){ |
|
19 | 1 | return $this->pdo->lastInsertId($name); |
|
20 | } |
||
21 | /** |
||
22 | * @var bool |
||
23 | * true on success or false on failure. |
||
24 | */ |
||
25 | public $success; |
||
26 | /** |
||
27 | * @var int |
||
28 | * the number of rows. |
||
29 | */ |
||
30 | public $rows; |
||
31 | /** |
||
32 | * |
||
33 | * @var \PDO |
||
34 | */ |
||
35 | public $pdo; |
||
36 | |||
37 | /** |
||
38 | * @var \PDOStatement |
||
39 | */ |
||
40 | public $st; |
||
41 | } |
||
42 | |||
43 | class SelectImpl |
||
44 | { |
||
45 | 28 | static public function select($context, $columns){ |
|
46 | 28 | $context->appendSql("SELECT $columns"); |
|
47 | 28 | } |
|
48 | } |
||
49 | |||
50 | class FromImpl |
||
51 | { |
||
52 | 27 | static public function from($context, $tables,$as=null){ |
|
53 | 27 | if($tables instanceof BasicRule){ |
|
54 | 1 | $context->appendSql("FROM (".$tables->context->sql.')'); |
|
55 | 1 | $context->params = array_merge($context->params,$tables->context->params); |
|
56 | 1 | }else { |
|
57 | 27 | $context->appendSql("FROM ".DB::wrap($tables)); |
|
58 | } |
||
59 | 27 | if($as){ |
|
60 | $context->appendSql("AS ".DB::wrap($as)); |
||
61 | } |
||
62 | 27 | } |
|
63 | } |
||
64 | |||
65 | class DeleteImpl |
||
66 | { |
||
67 | 7 | static public function deleteFrom($context, $from) |
|
68 | { |
||
69 | 7 | $context->appendSql("DELETE FROM ".DB::wrap($from)); |
|
70 | 7 | } |
|
71 | } |
||
72 | |||
73 | class JoinImpl |
||
74 | { |
||
75 | 5 | static public function join($context, $type, $table) { |
|
76 | 5 | $table = DB::wrap($table); |
|
77 | 5 | if($type){ |
|
78 | 3 | $context->appendSql("$type JOIN $table"); |
|
79 | 3 | }else{ |
|
80 | 2 | $context->appendSql("JOIN $table"); |
|
81 | } |
||
82 | 5 | } |
|
83 | } |
||
84 | |||
85 | class JoinOnImpl |
||
86 | { |
||
87 | 5 | static public function on($context, $condition) { |
|
88 | 5 | $context->appendSql("ON $condition"); |
|
89 | 5 | } |
|
90 | } |
||
91 | |||
92 | class ForUpdateImpl |
||
93 | { |
||
94 | 2 | static public function forUpdate($context){ |
|
95 | 2 | $context->appendSql("FOR UPDATE"); |
|
96 | 2 | } |
|
97 | } |
||
98 | |||
99 | class ForUpdateOfImpl |
||
100 | { |
||
101 | 1 | static public function of($context, $column){ |
|
102 | 1 | $column = DB::wrap($column); |
|
103 | 1 | $context->appendSql("OF $column"); |
|
104 | 1 | } |
|
105 | } |
||
106 | |||
107 | class InsertImpl |
||
108 | { |
||
109 | 8 | static public function insertInto($context, $table) { |
|
110 | 8 | $table = DB::wrap($table); |
|
111 | 8 | $context->appendSql("INSERT INTO $table"); |
|
112 | 8 | } |
|
113 | } |
||
114 | class ReplaceImpl |
||
115 | { |
||
116 | 2 | static public function replaceInto($context, $table) { |
|
117 | 2 | $table = DB::wrap($table); |
|
118 | 2 | $context->appendSql("REPLACE INTO $table"); |
|
119 | 2 | } |
|
120 | } |
||
121 | class ValuesImpl |
||
122 | { |
||
123 | 7 | static public function values(Context $context, array $values){ |
|
124 | 7 | $params = []; |
|
125 | 7 | $stubs = []; |
|
126 | 7 | foreach ($values as $v){ |
|
127 | 7 | if(is_a($v, Raw::class)){//直接拼接sql,不需要转义 |
|
128 | 4 | $stubs[]=$v->get(); |
|
129 | 4 | }else{ |
|
130 | 7 | $stubs[]='?'; |
|
131 | 7 | $params[] = $v; |
|
132 | } |
||
133 | 7 | } |
|
134 | 7 | $stubs = implode(',', $stubs); |
|
135 | |||
136 | 7 | View Code Duplication | if(array_keys($values) === range(0, count($values) - 1)){ |
0 ignored issues
–
show
|
|||
137 | //VALUES(val0, val1, val2) |
||
138 | 4 | $context->appendSql("VALUES($stubs)"); |
|
139 | |||
140 | 4 | }else{ |
|
141 | //(col0, col1, col2) VALUES(val0, val1, val2) |
||
142 | $columns = implode(',', array_map(function($k){return DB::wrap($k);}, array_keys($values))); |
||
143 | 3 | $context->appendSql("($columns) VALUES($stubs)",false); |
|
144 | } |
||
145 | 7 | $context->appendParams($params); |
|
146 | 7 | } |
|
147 | 3 | static public function batchValues(Context $context, array $values) |
|
148 | { |
||
149 | 3 | $count = count($values); |
|
150 | 3 | if($count == 0){ |
|
151 | return; |
||
152 | } |
||
153 | 3 | $keys = array_keys($values[0]); |
|
154 | 3 | $row = implode(',', self::toSql(array_values($values[0]))); |
|
155 | 3 | View Code Duplication | if($keys === range(0, count($keys) - 1)){ |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
156 | //VALUES(val0, val1, val2) |
||
157 | 2 | $context->appendSql("VALUES($row)"); |
|
158 | 2 | }else{ |
|
159 | //(col0, col1, col2) VALUES(val0, val1, val2) |
||
160 | $columns = implode(',', array_map(function($k){return DB::wrap($k);}, $keys)); |
||
161 | 1 | $context->appendSql("($columns) VALUES($row)",false); |
|
162 | } |
||
163 | 3 | for($i=1; $i<$count; $i++){ |
|
164 | 1 | $value = self::pick($keys, $values[$i]); |
|
165 | 1 | $row = implode(',', self::toSql($value)); |
|
166 | 1 | $context->appendSql(", ($row)",false); |
|
167 | 1 | } |
|
168 | 3 | } |
|
169 | |||
170 | 1 | static protected function pick(array $keys, array $values) |
|
171 | { |
||
172 | 1 | $res = []; |
|
173 | 1 | foreach ($keys as $key){ |
|
174 | 1 | array_key_exists($key, $values) or \PhpBoot\abort("key $key not exist from the given array"); |
|
175 | 1 | $res[$key] = $values[$key]; |
|
176 | 1 | } |
|
177 | 1 | return $res; |
|
178 | } |
||
179 | 3 | static protected function toSql(array $values) |
|
180 | { |
||
181 | 3 | foreach ($values as &$v){ |
|
182 | 3 | if($v instanceof Raw){ |
|
183 | 3 | $v = $v->get(); |
|
184 | 3 | }elseif(is_bool($v)){ |
|
185 | 3 | $v = $v?'true':'false'; |
|
186 | 3 | }elseif(!in_array(gettype($v), ['integer', 'boolean', 'double', 'float'])){ |
|
187 | 3 | $v = (string)$v; |
|
188 | 3 | $v = str_replace("\\", "\\\\", $v); |
|
189 | 3 | $v = str_replace("'", "\\'", $v); |
|
190 | 3 | $v = "'$v'"; |
|
191 | 3 | } |
|
192 | 3 | } |
|
193 | 3 | return $values; |
|
194 | } |
||
195 | } |
||
196 | |||
197 | class UpdateImpl |
||
198 | { |
||
199 | 11 | static public function update($context, $table){ |
|
200 | 11 | $table = DB::wrap($table); |
|
201 | 11 | $context->appendSql("UPDATE $table"); |
|
202 | 11 | } |
|
203 | } |
||
204 | |||
205 | class UpdateSetImpl |
||
206 | { |
||
207 | 11 | public function set(Context $context, $expr, $args){ |
|
208 | 11 | if(is_string($expr)){ |
|
209 | return $this->setExpr($context, $expr, $args); |
||
210 | }else{ |
||
211 | 11 | return $this->setArgs($context, $expr); |
|
212 | } |
||
213 | } |
||
214 | |||
215 | View Code Duplication | public function setExpr(Context $context, $expr, $args){ |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
216 | if($this->first){ |
||
217 | $this->first = false; |
||
218 | $prefix = 'SET '; |
||
219 | }else{ |
||
220 | $prefix = ','; |
||
221 | } |
||
222 | |||
223 | $context->appendSql("$prefix$expr",$prefix == 'SET '); |
||
224 | $context->appendParams($args); |
||
225 | |||
226 | } |
||
227 | 11 | View Code Duplication | public function setArgs(Context $context, $values){ |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
228 | 11 | $set = []; |
|
229 | 11 | $params = []; |
|
230 | 11 | foreach ($values as $k=>$v){ |
|
231 | 11 | $k = DB::wrap($k); |
|
232 | 11 | if(is_a($v, Raw::class)){//直接拼接sql,不需要转义 |
|
233 | 1 | $set[]= "$k=".$v->get(); |
|
234 | 1 | }else{ |
|
235 | 11 | $set[]= "$k=?"; |
|
236 | 11 | $params[]=$v; |
|
237 | } |
||
238 | 11 | } |
|
239 | 11 | if($this->first){ |
|
240 | 11 | $this->first = false; |
|
241 | 11 | $context->appendSql('SET '.implode(',', $set)); |
|
242 | 11 | $context->appendParams($params); |
|
243 | 11 | }else{ |
|
244 | $context->appendSql(','.implode(',', $set),false); |
||
245 | $context->appendParams($params); |
||
246 | } |
||
247 | 11 | } |
|
248 | private $first=true; |
||
249 | } |
||
250 | class OrderByImpl |
||
251 | { |
||
252 | 7 | public function orderByArgs(Context $context, $orders){ |
|
253 | 7 | if(empty($orders)){ |
|
254 | return $this; |
||
255 | } |
||
256 | 7 | $params = array(); |
|
257 | 7 | foreach ($orders as $k=>$v){ |
|
258 | 7 | if(is_integer($k)){ |
|
259 | 6 | $params[] = DB::wrap($v); |
|
260 | 6 | }else{ |
|
261 | 2 | $k = DB::wrap($k); |
|
262 | |||
263 | 2 | $v = strtoupper($v); |
|
264 | 2 | ($v =='DESC' || $v =='ASC') or \PhpBoot\abort( new \InvalidArgumentException("invalid params for orderBy(".json_encode($orders).")")); |
|
265 | |||
266 | 2 | $params[] = "$k $v"; |
|
267 | } |
||
268 | 7 | } |
|
269 | 7 | if($this->first){ |
|
270 | 7 | $this->first = false; |
|
271 | 7 | $context->appendSql('ORDER BY '.implode(',', $params)); |
|
272 | 7 | }else{ |
|
273 | 1 | $context->appendSql(','.implode(',', $params),false); |
|
274 | } |
||
275 | 7 | return $this; |
|
276 | } |
||
277 | 7 | public function orderBy(Context $context, $column, $order=null){ |
|
278 | 7 | if(is_string($column)){ |
|
279 | 7 | if($order === null){ |
|
280 | 6 | $column = [$column]; |
|
281 | 6 | }else{ |
|
282 | 2 | $column = [$column=>$order]; |
|
283 | } |
||
284 | 7 | } |
|
285 | 7 | return $this->orderByArgs($context, $column); |
|
286 | |||
287 | |||
288 | } |
||
289 | private $first=true; |
||
290 | } |
||
291 | |||
292 | class LimitImpl |
||
293 | { |
||
294 | 3 | static public function limit(Context $context, $size){ |
|
295 | 3 | $intSize = intval($size); |
|
296 | 3 | strval($intSize) == $size or \PhpBoot\abort( |
|
297 | new \InvalidArgumentException("invalid params for limit($size)")); |
||
298 | 3 | $context->appendSql("LIMIT $size"); |
|
299 | 3 | } |
|
300 | 1 | static public function limitWithOffset(Context $context, $start, $size){ |
|
301 | 1 | $intStart = intval($start); |
|
302 | 1 | $intSize = intval($size); |
|
303 | 1 | strval($intStart) == $start && strval($intSize) == $size or \PhpBoot\abort( |
|
304 | new \InvalidArgumentException("invalid params for limit($start, $size)")); |
||
305 | 1 | $context->appendSql("LIMIT $start,$size"); |
|
306 | 1 | } |
|
307 | } |
||
308 | |||
309 | class WhereImpl{ |
||
310 | |||
311 | 2 | static private function findQ($str,$offset = 0,$no=0){ |
|
312 | 2 | $found = strpos($str, '?', $offset); |
|
313 | 2 | if($no == 0 || $found === false){ |
|
314 | 2 | return $found; |
|
315 | } |
||
316 | 1 | return self::findQ($str, $found+1, $no-1); |
|
317 | } |
||
318 | |||
319 | 31 | static public function where(Context $context, $prefix, $expr, $args){ |
|
320 | 31 | if(empty($expr)){ |
|
321 | 1 | return; |
|
322 | } |
||
323 | 30 | if(is_callable($expr)){ |
|
324 | 3 | self::conditionClosure($context,$prefix, $expr); |
|
325 | 30 | }elseif (is_string($expr)){ |
|
326 | 15 | self::condition($context, $prefix, $expr, $args); |
|
327 | 15 | }else{ |
|
328 | 17 | self::conditionArgs($context, $prefix, $expr); |
|
329 | } |
||
330 | |||
331 | 30 | } |
|
332 | |||
333 | 3 | static public function conditionClosure(Context $context, $prefix, callable $callback){ |
|
334 | 3 | $context->appendSql($prefix.' ('); |
|
335 | 3 | $callback($context); |
|
336 | 3 | $context->appendSql(')'); |
|
337 | 3 | } |
|
338 | /** |
||
339 | * find like Mongodb query glossary |
||
340 | * whereArray( |
||
341 | * [ |
||
342 | * 'id'=>['>'=>1], |
||
343 | * 'name'=>'cym', |
||
344 | * ] |
||
345 | * ) |
||
346 | * 支持的操作符有 |
||
347 | * = 'id'=>['=' => 1] |
||
348 | * > 'id'=>['>' => 1] |
||
349 | * < 'id'=>['<' => 1] |
||
350 | * <> 'id'=>['<>' => 1] |
||
351 | * >= 'id'=>['>=' => 1] |
||
352 | * <= 'id'=>['<=' => 1] |
||
353 | * BETWEEN 'id'=>['BETWEEN' => [1 ,2]] |
||
354 | * LIKE 'id'=>['LIKE' => '1%'] |
||
355 | * IN 'id'=>['IN' => [1,2,3]] |
||
356 | * NOT IN 'id'=>['NOT IN' => [1,2,3]] |
||
357 | * @return void |
||
358 | */ |
||
359 | 17 | static public function conditionArgs(Context $context, $prefix, $args=[]){ |
|
360 | 17 | if($args ===null){ |
|
361 | return ; |
||
362 | } |
||
363 | 17 | $exprs = array(); |
|
364 | 17 | $params = array(); |
|
365 | 17 | foreach ($args as $k => $v){ |
|
366 | 17 | $k = DB::wrap($k); |
|
367 | 17 | if(!is_array($v)){ |
|
368 | 17 | $v = ['='=>$v]; |
|
369 | 17 | } |
|
370 | |||
371 | 17 | $ops = ['=', '>', '<', '<>', '>=', '<=', 'IN', 'NOT IN', 'BETWEEN', 'LIKE']; |
|
372 | 17 | $op = array_keys($v)[0]; |
|
373 | 17 | $op = strtoupper($op); |
|
374 | |||
375 | 17 | false !== array_search($op, $ops) or \PhpBoot\abort( |
|
376 | new \InvalidArgumentException("invalid param $op for whereArgs")); |
||
377 | |||
378 | 17 | $var = array_values($v)[0]; |
|
379 | 17 | if($op == 'IN' || $op == 'NOT IN'){ |
|
380 | 2 | $stubs = []; |
|
381 | |||
382 | 2 | if($var instanceof BasicRule){ |
|
383 | 1 | $stubs = "({$var->context->sql})"; |
|
384 | 1 | $params = array_merge($params, $var->context->params); |
|
385 | 1 | $exprs[] = "$k $op $stubs"; |
|
386 | 1 | }else{ |
|
387 | 1 | foreach ($var as $i){ |
|
388 | 1 | if(is_a($i, Raw::class)){ |
|
389 | 1 | $stubs[]=strval($i); |
|
390 | 1 | View Code Duplication | }elseif($i instanceof BasicRule){ |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
391 | $stubs = "({$i->context->sql})"; |
||
392 | $params = array_merge($params, $i->context->params); |
||
393 | }else{ |
||
394 | 1 | $stubs[]='?'; |
|
395 | 1 | $params[] = $i; |
|
396 | } |
||
397 | 1 | } |
|
398 | 1 | $stubs = implode(',', $stubs); |
|
399 | 1 | $exprs[] = "$k $op ($stubs)"; |
|
400 | } |
||
401 | 17 | }else if($op == 'BETWEEN'){ |
|
402 | 2 | $cond = "$k BETWEEN"; |
|
403 | 2 | View Code Duplication | if(is_a($var[0], Raw::class)){ |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
404 | $cond = "$cond ".strval($var[0]); |
||
405 | 2 | }elseif($var[0] instanceof BasicRule){ |
|
406 | 1 | $cond = "$cond ({$var[0]->context->sql})"; |
|
407 | 1 | $params = array_merge($params, $var[0]->context->params); |
|
408 | 1 | }else{ |
|
409 | 1 | $cond = "$cond ?"; |
|
410 | 1 | $params[] = $var[0]; |
|
411 | } |
||
412 | 2 | View Code Duplication | if(is_a($var[1], Raw::class)){ |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
413 | 1 | $cond = "$cond AND ".strval($var[1]); |
|
414 | 2 | }elseif($var[1] instanceof BasicRule){ |
|
415 | 1 | $cond = "$cond AND ({$var[1]->context->sql})"; |
|
416 | 1 | $params = array_merge($params, $var[1]->context->params); |
|
417 | 1 | }else{ |
|
418 | $cond = "$cond AND ?"; |
||
419 | $params[] = $var[1]; |
||
420 | } |
||
421 | 2 | $exprs[] = $cond; |
|
422 | 2 | }else{ |
|
423 | 17 | if(is_a($var, Raw::class)){ |
|
424 | 1 | $exprs[] = "$k $op ".strval($var); |
|
425 | 17 | }elseif($var instanceof BasicRule){ |
|
426 | $exprs[] = "$k $op {$var->context->sql}"; |
||
427 | $params = array_merge($params, $var->context->params); |
||
428 | }else{ |
||
429 | 17 | $exprs[] = "$k $op ?"; |
|
430 | 17 | $params[] = $var; |
|
431 | } |
||
432 | } |
||
433 | 17 | } |
|
434 | |||
435 | 17 | self::condition($context, $prefix, implode(' AND ', $exprs), $params); |
|
436 | 17 | } |
|
437 | 30 | static public function condition(Context $context, $prefix, $expr, $args){ |
|
438 | 30 | if(!empty($expr)){ |
|
439 | 30 | $expr = "($expr)"; |
|
440 | 30 | if($args){ |
|
441 | //因为PDO不支持绑定数组变量, 这里需要手动展开数组 |
||
442 | //也就是说把 where("id IN(?)", [1,2]) 展开成 where("id IN(?,?)", 1,2) |
||
443 | 29 | $cutted = null; |
|
444 | 29 | $cut = null; |
|
445 | 29 | $toReplace = array(); |
|
446 | |||
447 | 29 | $newArgs=array(); |
|
448 | //找到所有数组对应的?符位置 |
||
449 | 29 | foreach ($args as $k =>$arg){ |
|
450 | 29 | if(is_array($arg) || is_a($arg, Raw::class) || is_a($arg, BasicRule::class)){ |
|
451 | |||
452 | 2 | if(!$cutted){ |
|
0 ignored issues
–
show
The expression
$cutted of type null|string is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
453 | 2 | $cut = new NestedStringCut($expr); |
|
454 | 2 | $cutted = $cut->getText(); |
|
455 | 2 | } |
|
456 | //找到第$k个?符 |
||
457 | 2 | $pos = self::findQ($cutted, 0, $k); |
|
458 | 2 | $pos = $cut->mapPos($pos); |
|
459 | 2 | $pos !== false or \PhpBoot\abort( |
|
460 | new \InvalidArgumentException("unmatched params and ? @ $expr")); |
||
461 | |||
462 | 2 | if(is_array($arg)){ |
|
463 | 1 | $stubs = []; |
|
464 | 1 | foreach ($arg as $i){ |
|
465 | 1 | if(is_a($i, Raw::class)){ |
|
466 | 1 | $stubs[] = strval($i); |
|
467 | 1 | }else{ |
|
468 | 1 | $stubs[] = '?'; |
|
469 | 1 | $newArgs[] = $i; |
|
470 | } |
||
471 | 1 | } |
|
472 | 1 | $stubs = implode(',', $stubs); |
|
473 | 2 | View Code Duplication | }elseif($arg instanceof BasicRule){ |
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
474 | 1 | $stubs = "({$arg->context->sql})"; |
|
475 | 1 | $newArgs = array_merge($newArgs, $arg->context->params); |
|
476 | 1 | }else{ |
|
477 | 1 | $stubs = strval($arg); |
|
478 | } |
||
479 | 2 | $toReplace[] = [$pos, $stubs]; |
|
480 | |||
481 | 2 | }else{ |
|
482 | 29 | $newArgs[]=$arg; |
|
483 | } |
||
484 | 29 | } |
|
485 | |||
486 | 29 | if(count($toReplace)){ |
|
487 | 2 | $toReplace = array_reverse($toReplace); |
|
488 | 2 | foreach ($toReplace as $i){ |
|
489 | 2 | list($pos, $v) = $i; |
|
490 | 2 | $expr = substr($expr, 0, $pos).$v.substr($expr, $pos+1); |
|
491 | 2 | } |
|
492 | 2 | $args = $newArgs; |
|
493 | 2 | } |
|
494 | 29 | } |
|
495 | 30 | if($prefix){ |
|
496 | 30 | $context->appendSql($prefix.' '.$expr); |
|
497 | 30 | }else{ |
|
498 | 3 | $context->appendSql($expr); |
|
499 | } |
||
500 | |||
501 | 30 | if($args){ |
|
502 | 29 | $context->appendParams($args); |
|
503 | 29 | } |
|
504 | 30 | } |
|
505 | 30 | } |
|
506 | } |
||
507 | |||
508 | class GroupByImpl{ |
||
509 | 5 | static public function groupBy(Context $context, $column){ |
|
510 | 5 | $column = DB::wrap($column); |
|
511 | 5 | $context->appendSql("GROUP BY $column"); |
|
512 | 5 | } |
|
513 | } |
||
514 | |||
515 | class ExecImpl |
||
516 | { |
||
517 | /** |
||
518 | * |
||
519 | * @param Context $context |
||
520 | * @param $exceOnError boolean whether throw exceptions |
||
521 | * @return ExecResult |
||
522 | * @throws DBException|\Exception |
||
523 | */ |
||
524 | 28 | static public function exec($context) { |
|
525 | try{ |
||
526 | 28 | $st = $context->connection->prepare($context->sql); |
|
527 | 28 | $success = $st->execute($context->params); |
|
528 | 28 | return new ExecResult($success, $context->connection, $st); |
|
529 | }catch (\Exception $e){ |
||
530 | \PhpBoot\abort(new DBException($context, $e->getMessage(),$e->getCode()), ['sql'=>$context->sql, 'params'=>$context->params] ); |
||
531 | return null; |
||
532 | } |
||
533 | } |
||
534 | /** |
||
535 | * |
||
536 | * @param Context $context |
||
537 | * @param string|false $asDict return as dict or array |
||
0 ignored issues
–
show
There is no parameter named
$asDict . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
538 | * @return false|array |
||
539 | * @throws DBException|\Exception |
||
540 | */ |
||
541 | 28 | static public function get($context, $dictAs=false){ |
|
542 | |||
543 | try{ |
||
544 | 28 | $st = $context->connection->prepare($context->sql); |
|
545 | 28 | if($st->execute($context->params)){ |
|
546 | $res = $st->fetchAll(\PDO::FETCH_ASSOC); |
||
547 | if ($dictAs){ |
||
548 | $dict= []; |
||
549 | foreach ($res as $i){ |
||
550 | $dict[$i[$dictAs]]=$i; |
||
551 | } |
||
552 | return $context->handleResult($dict); |
||
553 | } |
||
554 | return $context->handleResult($res); |
||
555 | }else{ |
||
556 | 28 | return false; |
|
557 | } |
||
558 | }catch (\Exception $e){ |
||
559 | \PhpBoot\abort(new DBException($context, $e->getMessage(),$e->getCode()), ['sql'=>$context->sql, 'params'=>$context->params] ); |
||
560 | return false; |
||
561 | } |
||
562 | |||
563 | } |
||
564 | |||
565 | /** |
||
566 | * @param Context $context |
||
567 | * @return int|false |
||
568 | * @throws DBException|\Exception |
||
569 | */ |
||
570 | static public function count($context){ |
||
571 | |||
572 | $found = []; |
||
573 | if(!preg_match('/\bselect\b/i', $context->sql, $found, PREG_OFFSET_CAPTURE) || |
||
574 | count($found)==0){ |
||
575 | \PhpBoot\abort(new \PDOException("can not use count(*) without select")); |
||
576 | } |
||
577 | list($chars, $columnBegin) = $found[0]; |
||
0 ignored issues
–
show
The assignment to
$chars is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
![]() |
|||
578 | $columnBegin = $columnBegin + strlen('select')+1; |
||
579 | |||
580 | $columnEnd = 0; |
||
581 | $found = []; |
||
582 | try{ |
||
583 | if(!preg_match('/\bfrom\b/i', $context->sql, $found, PREG_OFFSET_CAPTURE) || |
||
584 | count($found)==0){ |
||
585 | $columnEnd = strlen($context->sql); |
||
586 | }else{ |
||
587 | list($chars, $columnEnd) = $found[0]; |
||
0 ignored issues
–
show
The assignment to
$chars is unused. Consider omitting it like so list($first,,$third) .
This checks looks for assignemnts to variables using the Consider the following code example. <?php
function returnThreeValues() {
return array('a', 'b', 'c');
}
list($a, $b, $c) = returnThreeValues();
print $a . " - " . $c;
Only the variables Instead, the list call could have been. list($a,, $c) = returnThreeValues();
![]() |
|||
588 | } |
||
589 | $sql = substr($context->sql, 0, $columnBegin); |
||
590 | $sql .= ' COUNT(*) as `count` '; |
||
591 | $sql .= substr($context->sql, $columnEnd); |
||
592 | |||
593 | $st = $context->connection->prepare($sql); |
||
594 | if($st->execute($context->params)){ |
||
595 | $res = $st->fetchAll(\PDO::FETCH_ASSOC); |
||
596 | return intval($res[0]['count']); |
||
597 | }else{ |
||
598 | return false; |
||
599 | } |
||
600 | }catch (\Exception $e){ |
||
601 | \PhpBoot\abort(new DBException($context, $e->getMessage(),$e->getCode()), ['sql'=>$context->sql, 'params'=>$context->params] ); |
||
602 | return false; |
||
603 | } |
||
604 | } |
||
605 | } |
||
606 | class OnDuplicateKeyUpdateImpl |
||
607 | { |
||
608 | 1 | public function set($context, $column, $value){ |
|
609 | 1 | if(is_string($column)){ |
|
610 | 1 | $this->setExpr($context, $column, $value); |
|
611 | 1 | }else{ |
|
612 | 1 | $this->setArgs($context, $column); |
|
613 | } |
||
614 | 1 | } |
|
615 | |||
616 | 1 | View Code Duplication | public function setExpr($context, $expr, $args){ |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
617 | 1 | $prefix = ''; |
|
0 ignored issues
–
show
$prefix is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
618 | 1 | if($this->first){ |
|
619 | 1 | $this->first = false; |
|
620 | 1 | $prefix = 'ON DUPLICATE KEY UPDATE '; |
|
621 | 1 | }else{ |
|
622 | $prefix = ','; |
||
623 | } |
||
624 | |||
625 | 1 | $context->appendSql("$prefix$expr",$prefix == 'ON DUPLICATE KEY UPDATE '); |
|
626 | 1 | $context->appendParams($args); |
|
627 | |||
628 | 1 | } |
|
629 | 1 | View Code Duplication | public function setArgs($context, $values){ |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
630 | 1 | $set = []; |
|
631 | 1 | $params = []; |
|
632 | 1 | foreach ($values as $k=>$v){ |
|
633 | 1 | $k = DB::wrap($k); |
|
634 | 1 | if(is_a($v, Raw::class)){//直接拼接sql,不需要转义 |
|
635 | 1 | $set[]= "$k=".$v->get(); |
|
636 | 1 | }else{ |
|
637 | $set[]= "$k=?"; |
||
638 | $params[]=$v; |
||
639 | } |
||
640 | 1 | } |
|
641 | 1 | if($this->first){ |
|
642 | 1 | $this->first = false; |
|
643 | 1 | $context->appendSql('ON DUPLICATE KEY UPDATE '.implode(',', $set)); |
|
644 | 1 | $context->appendParams($params); |
|
645 | 1 | }else{ |
|
646 | $context->appendSql(','.implode(',', $set),false); |
||
647 | $context->appendParams($params); |
||
648 | } |
||
649 | 1 | } |
|
650 | private $first=true; |
||
651 | } |
||
652 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.