1 | <?php |
||||||
2 | |||||||
3 | namespace DB; |
||||||
4 | |||||||
5 | use JSON\json; |
||||||
6 | use MVC\Exception; |
||||||
7 | use PDO as GlobalPDO; |
||||||
8 | use PDOException; |
||||||
9 | use mysqli as MYSQLi; |
||||||
10 | |||||||
11 | /* |
||||||
12 | function SQL_Connect ($user, $pass, $dbname, $host = "localhost", $charset = "utf8mb4"); |
||||||
13 | function SQL_Exec ($pdo, $query, $values = false); |
||||||
14 | function SQL_Fetch ($pdo, $query, $values = false); |
||||||
15 | function SQL_MultiFetch ($pdo, $query, $values = false); |
||||||
16 | function SQL_LastID ($pdo); |
||||||
17 | function SQL_Error ($e, $query); |
||||||
18 | |||||||
19 | ------------------------------------------------------------ |
||||||
20 | |||||||
21 | Define PDO_DEBUG for detailed error messages. |
||||||
22 | |||||||
23 | PDO_DEBUG values: |
||||||
24 | |||||||
25 | 1: Print the error message. |
||||||
26 | 2: Print also the SQL Statement. |
||||||
27 | 3: Print SQL Statement and traceback with detailed information where the error occurs. |
||||||
28 | |||||||
29 | Example: define ("PDO_DEBUG", "2"); |
||||||
30 | |||||||
31 | */ |
||||||
32 | |||||||
33 | if (!defined('PDO_DEBUG')) { |
||||||
34 | $env = \MVC\router::get_env(); |
||||||
35 | if ('development' == $env) { |
||||||
36 | $env = '3'; |
||||||
37 | } else { |
||||||
38 | $env = '1'; |
||||||
39 | } |
||||||
40 | define('PDO_DEBUG', $env); |
||||||
41 | } |
||||||
42 | |||||||
43 | /** |
||||||
44 | * Database Management. |
||||||
45 | * |
||||||
46 | * @author DimasLanjaka <[email protected]> |
||||||
47 | */ |
||||||
48 | class pdo |
||||||
49 | { |
||||||
50 | protected $userdb; |
||||||
51 | protected $passdb; |
||||||
52 | protected $namedb; |
||||||
53 | protected $hostdb; |
||||||
54 | protected $charsetdb; |
||||||
55 | /** |
||||||
56 | * MYSQLI Instance |
||||||
57 | * |
||||||
58 | * @var mysqli |
||||||
59 | */ |
||||||
60 | protected $mysqli; |
||||||
61 | /** |
||||||
62 | * Shimmer MySQL |
||||||
63 | * |
||||||
64 | * @var \UniversalFramework\MySQL |
||||||
65 | */ |
||||||
66 | protected $shimmer; |
||||||
67 | /** |
||||||
68 | * PDO instance. |
||||||
69 | * |
||||||
70 | * @var GlobalPDO |
||||||
71 | */ |
||||||
72 | protected $pdo; |
||||||
73 | |||||||
74 | public function __construct($user = null, $pass = null, $dbname = null, $host = 'localhost', $charset = 'utf8mb4') |
||||||
75 | { |
||||||
76 | if (!empty($user) && !empty($dbname)) { |
||||||
77 | $this->connect($user, $pass, $dbname, $host, $charset); |
||||||
78 | } else { |
||||||
79 | exit('Database wrong ' . json_encode(func_get_args())); |
||||||
0 ignored issues
–
show
|
|||||||
80 | } |
||||||
81 | } |
||||||
82 | |||||||
83 | /** |
||||||
84 | * Get enum or set value as associative arrays |
||||||
85 | * |
||||||
86 | * @param string $table |
||||||
87 | * @param string $field |
||||||
88 | * @return array |
||||||
89 | */ |
||||||
90 | public function get_enum_set_values($table, $field) |
||||||
91 | { |
||||||
92 | $type = $this->pdo |
||||||
93 | ->query("SHOW COLUMNS FROM {$table} WHERE Field = '{$field}'")->fetch(); |
||||||
94 | if (isset($type['Type'])) { |
||||||
95 | preg_match("/^(enum|set)\(\'(.*)\'\)$/", $type['Type'], $matches); |
||||||
96 | if (isset($matches[2])) { |
||||||
97 | $enum = explode("','", $matches[2]); |
||||||
98 | return $enum; |
||||||
99 | } |
||||||
100 | } |
||||||
101 | return []; |
||||||
102 | } |
||||||
103 | //UPDATE `roles` SET `allow` = 'edit-categories,edit-user,add-user' WHERE `roles`.`id` = 1; |
||||||
104 | public function set_multiple_value(string $table, string $field, array $values, string $where) |
||||||
105 | { |
||||||
106 | $combine = implode(',', $values); |
||||||
107 | |||||||
108 | $sql = "UPDATE `$table` SET `$field` = '$combine' $where;"; |
||||||
0 ignored issues
–
show
|
|||||||
109 | } |
||||||
110 | |||||||
111 | /** |
||||||
112 | * Add value to SET field |
||||||
113 | * |
||||||
114 | * @param string $table |
||||||
115 | * @param string $field |
||||||
116 | * @param string $new_value |
||||||
117 | * @return array |
||||||
118 | */ |
||||||
119 | public function add_set_value(string $table, string $field, $new_value) |
||||||
120 | { |
||||||
121 | $sets = ["'$new_value'"]; |
||||||
122 | foreach ($this->get_enum_set_values($table, $field) as $value) { |
||||||
123 | $sets[] = "'$value'"; |
||||||
124 | } |
||||||
125 | ksort($sets); |
||||||
126 | $combine = implode(',', array_unique($sets)); |
||||||
127 | $sql = "ALTER TABLE `$table` CHANGE `$field` `$field` SET($combine);"; |
||||||
128 | return $this->query($sql)->exec(); |
||||||
129 | } |
||||||
130 | |||||||
131 | /** |
||||||
132 | * Remove value from SET field |
||||||
133 | * |
||||||
134 | * @param string $table |
||||||
135 | * @param string $field |
||||||
136 | * @param string $old_value |
||||||
137 | * @return array |
||||||
138 | */ |
||||||
139 | public function remove_set_value(string $table, string $field, $old_value) |
||||||
140 | { |
||||||
141 | $sets = []; |
||||||
142 | foreach ($this->get_enum_set_values($table, $field) as $value) { |
||||||
143 | $sets[] = "'$value'"; |
||||||
144 | } |
||||||
145 | if (isset($sets[$old_value])) { |
||||||
146 | unset($set[$old_value]); |
||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
147 | } |
||||||
148 | ksort($sets); |
||||||
149 | $combine = implode(',', array_unique($sets)); |
||||||
150 | $sql = "ALTER TABLE `$table` CHANGE `$field` `$field` SET($combine);"; |
||||||
151 | return $this->query($sql)->exec(); |
||||||
152 | } |
||||||
153 | |||||||
154 | /** |
||||||
155 | * Check table exists. |
||||||
156 | * |
||||||
157 | * @return bool |
||||||
158 | */ |
||||||
159 | public function check_table(string $table) |
||||||
160 | { |
||||||
161 | $check = $this->query("SHOW TABLES LIKE '$table';")->row_array(); |
||||||
162 | |||||||
163 | return !empty($check); |
||||||
164 | } |
||||||
165 | |||||||
166 | /** |
||||||
167 | * Get mysqli instances |
||||||
168 | * |
||||||
169 | * @return mysqli |
||||||
170 | */ |
||||||
171 | public function mysqli() |
||||||
172 | { |
||||||
173 | return $this->mysqli; |
||||||
174 | } |
||||||
175 | |||||||
176 | /** |
||||||
177 | * Escape query sql |
||||||
178 | * |
||||||
179 | * @param string $query |
||||||
180 | * @return string |
||||||
181 | */ |
||||||
182 | public function escape(string $query = null) |
||||||
183 | { |
||||||
184 | $this->mysqli->query('SET NAMES utf8mb4;'); |
||||||
185 | $new_data = $query != null ? $query : $this->query; |
||||||
0 ignored issues
–
show
|
|||||||
186 | //$new_data = $this->mysqli->real_escape_string(); |
||||||
187 | //$new_data = addcslashes($new_data, '%_$'); |
||||||
188 | //$new_data = htmlspecialchars($new_data, ENT_NOQUOTES); |
||||||
189 | $new_data = preg_quote($new_data); |
||||||
190 | return $new_data; |
||||||
191 | } |
||||||
192 | |||||||
193 | public function descape(string $query = null) |
||||||
194 | { |
||||||
195 | $this->mysqli->query('SET NAMES utf8mb4;'); |
||||||
196 | $new_data = $query != null ? $query : $this->query; |
||||||
0 ignored issues
–
show
|
|||||||
197 | //$new_data = htmlspecialchars_decode($new_data); |
||||||
198 | $new_data = stripcslashes($new_data); |
||||||
199 | return $new_data; |
||||||
200 | } |
||||||
201 | |||||||
202 | /** |
||||||
203 | * Set MySQL Timezone. |
||||||
204 | * |
||||||
205 | * @requires superuser access |
||||||
206 | * |
||||||
207 | * @return array |
||||||
208 | */ |
||||||
209 | public function setTimezone(string $gmt = '+7:00') |
||||||
210 | { |
||||||
211 | return $this->query("SET GLOBAL time_zone = '$gmt'; |
||||||
212 | SET SESSION time_zone = '$gmt'; |
||||||
213 | SELECT @@GLOBAL.time_zone, @@SESSION.time_zone;")->exec(); |
||||||
214 | } |
||||||
215 | |||||||
216 | /** |
||||||
217 | * Connect PDO. |
||||||
218 | * |
||||||
219 | * @param string $user database user |
||||||
220 | * @param string $pass database password |
||||||
221 | * @param string $dbname database name |
||||||
222 | * @param string $host database host |
||||||
223 | * @param string $charset database charset |
||||||
224 | * |
||||||
225 | * @return \PDO |
||||||
226 | */ |
||||||
227 | public function connect($user, $pass, $dbname, $host = 'localhost', $charset = 'utf8mb4') |
||||||
228 | { |
||||||
229 | $this->userdb = $user; |
||||||
230 | $this->passdb = $pass; |
||||||
231 | $this->namedb = $dbname; |
||||||
232 | $this->hostdb = $host; |
||||||
233 | $this->charsetdb = $charset; |
||||||
234 | $options = [ |
||||||
235 | GlobalPDO::ATTR_ERRMODE => GlobalPDO::ERRMODE_EXCEPTION, |
||||||
236 | GlobalPDO::ATTR_DEFAULT_FETCH_MODE => GlobalPDO::FETCH_ASSOC, |
||||||
237 | GlobalPDO::ATTR_EMULATE_PREPARES => false, |
||||||
238 | GlobalPDO::ATTR_CASE => GlobalPDO::CASE_NATURAL, |
||||||
239 | GlobalPDO::ATTR_ORACLE_NULLS => GlobalPDO::NULL_EMPTY_STRING, |
||||||
240 | GlobalPDO::ATTR_STATEMENT_CLASS => ['\DB\EPDOStatement', []], |
||||||
241 | ]; |
||||||
242 | |||||||
243 | $pdo = null; |
||||||
0 ignored issues
–
show
|
|||||||
244 | try { |
||||||
245 | $pdo = new GlobalPDO("mysql:host=$host;dbname=$dbname;charset=$charset", $user, $pass, $options); |
||||||
246 | $this->mysqli = new MYSQLi($host, $user, $pass, $dbname); |
||||||
247 | $this->shimmer = new \UniversalFramework\MySQL($this->mysqli); |
||||||
248 | } catch (PDOException $e) { |
||||||
249 | exit($e->getMessage()); |
||||||
0 ignored issues
–
show
|
|||||||
250 | $this->SQL_Error($e); |
||||||
0 ignored issues
–
show
$this->SQL_Error($e) is not reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||||||
251 | } |
||||||
252 | $this->pdo = $pdo; |
||||||
253 | |||||||
254 | return $pdo; |
||||||
255 | } |
||||||
256 | |||||||
257 | /** |
||||||
258 | * Get mysql shimmer instances |
||||||
259 | * |
||||||
260 | * @return \UniversalFramework\MySQL |
||||||
261 | */ |
||||||
262 | function shimmer() |
||||||
0 ignored issues
–
show
|
|||||||
263 | { |
||||||
264 | return $this->shimmer; |
||||||
265 | } |
||||||
266 | |||||||
267 | /** |
||||||
268 | * Switch database. |
||||||
269 | * |
||||||
270 | * @todo Switch between databases |
||||||
271 | * |
||||||
272 | * @return $this |
||||||
273 | */ |
||||||
274 | public function switch(string $dbname) |
||||||
275 | { |
||||||
276 | $this->query('USE ' . $dbname)->exec(); |
||||||
277 | |||||||
278 | return $this; |
||||||
279 | } |
||||||
280 | |||||||
281 | private $from; |
||||||
282 | private $query = ''; |
||||||
283 | |||||||
284 | public function query(string $sql) |
||||||
285 | { |
||||||
286 | $this->query = $this->trim($sql); |
||||||
287 | |||||||
288 | return $this; |
||||||
289 | } |
||||||
290 | |||||||
291 | public function prep(array $prep) |
||||||
292 | { |
||||||
293 | $stmt = $this->pdo->prepare($this->query); |
||||||
294 | foreach ($prep as $key => $value) { |
||||||
295 | $stmt->bindParam(':' . preg_replace('/^\:/s', '', $key), $value, GlobalPDO::PARAM_STR); |
||||||
296 | } |
||||||
297 | //return $stmt->execute(); |
||||||
298 | } |
||||||
299 | |||||||
300 | /** |
||||||
301 | * Get where parameter is equals. |
||||||
302 | * |
||||||
303 | * @return $this |
||||||
304 | */ |
||||||
305 | public function get_where(string $tbl, array $param = []) |
||||||
306 | { |
||||||
307 | $this->query .= " SELECT * FROM `$tbl` WHERE "; |
||||||
308 | foreach ($param as $key => $value) { |
||||||
309 | $this->query .= " `$key` = '$value' "; |
||||||
310 | } |
||||||
311 | |||||||
312 | return $this; |
||||||
313 | } |
||||||
314 | |||||||
315 | /** |
||||||
316 | * Reset Query. |
||||||
317 | * |
||||||
318 | * @return $this |
||||||
319 | */ |
||||||
320 | public function resetQuery() |
||||||
321 | { |
||||||
322 | $this->query = ''; |
||||||
323 | |||||||
324 | return $this; |
||||||
325 | } |
||||||
326 | |||||||
327 | /** |
||||||
328 | * SELECT tableName. |
||||||
329 | * |
||||||
330 | * @param string $tbl table_name |
||||||
331 | * @param string $row separated with comma |
||||||
332 | * * Ex: name, date |
||||||
333 | * |
||||||
334 | * @return $this |
||||||
335 | */ |
||||||
336 | public function select(string $tbl, string $row = '*') |
||||||
337 | { |
||||||
338 | $this->clear(); |
||||||
339 | $this->from = $tbl; |
||||||
340 | $this->query .= " SELECT $row FROM $tbl "; |
||||||
341 | |||||||
342 | return $this; |
||||||
343 | } |
||||||
344 | |||||||
345 | /** |
||||||
346 | * Clear last queries |
||||||
347 | * |
||||||
348 | * @return $this |
||||||
349 | */ |
||||||
350 | function clear() |
||||||
0 ignored issues
–
show
|
|||||||
351 | { |
||||||
352 | $this->query = ''; |
||||||
353 | return $this; |
||||||
354 | } |
||||||
355 | |||||||
356 | /** |
||||||
357 | * Search database by row and keyword. |
||||||
358 | */ |
||||||
359 | public function search(array $data, string $separated = 'OR') |
||||||
360 | { |
||||||
361 | $i = 0; |
||||||
362 | foreach ($data as $key => $value) { |
||||||
363 | if (0 == $i) { |
||||||
364 | $this->query .= " WHERE $key LIKE '%$value%' "; |
||||||
365 | } else { |
||||||
366 | $this->query .= " $separated $key LIKE '%$value%' "; |
||||||
367 | } |
||||||
368 | ++$i; |
||||||
369 | } |
||||||
370 | |||||||
371 | return $this; |
||||||
372 | } |
||||||
373 | |||||||
374 | public function adv_search(array $data = ['OR' => ['key' => 'keyword', 'key2' => 'keyword2'], 'AND' => ['key' => 'keyword', 'key2' => 'keyword2']]) |
||||||
375 | { |
||||||
376 | if (isset($data['OR'], $data['or'])) { |
||||||
377 | $or = isset($data['OR']) ? $data['OR'] : $data['or']; |
||||||
378 | $i = 0; |
||||||
379 | foreach ($or as $key => $value) { |
||||||
380 | if (0 == $i) { |
||||||
381 | $this->query .= " WHERE $key LIKE '%$value%' "; |
||||||
382 | } else { |
||||||
383 | $this->query .= " OR $key LIKE '%$value%' "; |
||||||
384 | } |
||||||
385 | } |
||||||
386 | ++$i; |
||||||
387 | } |
||||||
388 | } |
||||||
389 | |||||||
390 | public function insert($tbl, array $data = []) |
||||||
391 | { |
||||||
392 | $this->query .= 'INSERT INTO '; |
||||||
393 | $dbkey = " `$tbl` ( "; |
||||||
394 | $dbval = ' VALUES( '; |
||||||
395 | $keys = array_keys($data); |
||||||
396 | $values = array_values($data); |
||||||
397 | for ($i = 0; $i < count($data); ++$i) { |
||||||
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||||||
398 | if ($i == count($data) - 1) { // if last iteration |
||||||
399 | $dbkey .= " `{$keys[$i]}` ) "; |
||||||
400 | $this->query .= $dbkey; |
||||||
401 | $dbval .= " '{$values[$i]}' ) "; |
||||||
402 | $this->query .= $dbval; |
||||||
403 | } else { |
||||||
404 | $dbkey .= " `{$keys[$i]}`, "; |
||||||
405 | $dbval .= " '{$values[$i]}', "; |
||||||
406 | } |
||||||
407 | } |
||||||
408 | |||||||
409 | return $this; |
||||||
410 | } |
||||||
411 | |||||||
412 | public function update(string $tbl, array $data, array $is_equals) |
||||||
413 | { |
||||||
414 | $this->query .= " UPDATE `$tbl` SET "; |
||||||
415 | foreach ($data as $key => $value) { |
||||||
416 | $this->query .= " `$key`='$value' "; |
||||||
417 | } |
||||||
418 | $this->query .= ' WHERE '; |
||||||
419 | foreach ($is_equals as $key => $value) { |
||||||
420 | $this->query .= " `$key` = '$value' "; |
||||||
421 | } |
||||||
422 | |||||||
423 | return $this; |
||||||
424 | } |
||||||
425 | |||||||
426 | public function sum(string $tbl, array $data, array $is_equals) |
||||||
427 | { |
||||||
428 | $this->query .= " UPDATE `$tbl` SET "; |
||||||
429 | foreach ($data as $key => $value) { |
||||||
430 | if (!is_numeric($value)) { |
||||||
431 | throw new Exception("$value must be instance of number, instead of " . gettype($value), 1); |
||||||
432 | } |
||||||
433 | $this->query .= " `$key`=$key + $value "; |
||||||
434 | } |
||||||
435 | $this->query .= ' WHERE '; |
||||||
436 | foreach ($is_equals as $key => $value) { |
||||||
437 | $this->query .= " `$key` = '$value' "; |
||||||
438 | } |
||||||
439 | |||||||
440 | return $this; |
||||||
441 | } |
||||||
442 | |||||||
443 | /** |
||||||
444 | * PDO Instance. |
||||||
445 | * |
||||||
446 | * @return GlobalPDO |
||||||
447 | */ |
||||||
448 | public function pdo() |
||||||
449 | { |
||||||
450 | return $this->pdo; |
||||||
451 | } |
||||||
452 | |||||||
453 | public function insert_update($tbl, array $data, array $onduplicate) |
||||||
454 | { |
||||||
455 | $this->query .= ' INSERT INTO '; |
||||||
456 | $dbkey = " `$tbl` ( "; |
||||||
457 | $dbval = ' VALUES( '; |
||||||
458 | $keys = array_keys($data); |
||||||
459 | $values = array_values($data); |
||||||
460 | for ($i = 0; $i < count($data); ++$i) { |
||||||
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||||||
461 | $V = $values[$i]; |
||||||
462 | $V = str_replace('\'', '\\\'', $V); |
||||||
463 | if ($i == count($data) - 1) { // if last iteration |
||||||
464 | $dbkey .= " `{$keys[$i]}` ) "; |
||||||
465 | $this->query .= $dbkey; |
||||||
466 | $dbval .= " '{$V}' ) "; |
||||||
467 | $this->query .= $dbval; |
||||||
468 | } else { |
||||||
469 | $dbkey .= " `{$keys[$i]}`, "; |
||||||
470 | $dbval .= " '{$V}', "; |
||||||
471 | } |
||||||
472 | } |
||||||
473 | $this->query .= ' ON DUPLICATE KEY UPDATE '; |
||||||
474 | $dup_keys = array_keys($onduplicate); |
||||||
475 | $dup_values = array_values($onduplicate); |
||||||
476 | for ($i = 0; $i < count($onduplicate); ++$i) { |
||||||
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||||||
477 | if ($i == count($onduplicate) - 1) { // last iteration |
||||||
478 | $this->query .= " `{$dup_keys[$i]}` = '{$dup_values[$i]}' "; |
||||||
479 | } else { |
||||||
480 | $this->query .= " `{$dup_keys[$i]}` = '{$dup_values[$i]}', "; |
||||||
481 | } |
||||||
482 | } |
||||||
483 | //var_dump($this->query); |
||||||
484 | |||||||
485 | return $this; |
||||||
486 | } |
||||||
487 | |||||||
488 | public function replace(string $tbl, array $data) |
||||||
489 | { |
||||||
490 | $this->query .= ' REPLACE INTO '; |
||||||
491 | $dbkey = " `$tbl` ( "; |
||||||
492 | $dbval = ' VALUES( '; |
||||||
493 | $keys = array_keys($data); |
||||||
494 | $values = array_values($data); |
||||||
495 | for ($i = 0; $i < count($data); ++$i) { |
||||||
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||||||
496 | if ($i == count($data) - 1) { // if last iteration |
||||||
497 | $dbkey .= " `{$keys[$i]}` ) "; |
||||||
498 | $this->query .= $dbkey; |
||||||
499 | $dbval .= " `{$values[$i]}` ) "; |
||||||
500 | $this->query .= $dbval; |
||||||
501 | } else { |
||||||
502 | $dbkey .= " `{$keys[$i]}`, "; |
||||||
503 | $dbval .= " `{$values[$i]}`, "; |
||||||
504 | } |
||||||
505 | } |
||||||
506 | |||||||
507 | return $this; |
||||||
508 | } |
||||||
509 | |||||||
510 | /** |
||||||
511 | * Fetch from Queries ($this->query) |
||||||
512 | * |
||||||
513 | * @return array $var['result'] for result |
||||||
514 | */ |
||||||
515 | public function fetch() |
||||||
516 | { |
||||||
517 | $result = ['query' => $this->query, 'error' => true]; |
||||||
518 | /** |
||||||
519 | * @var statement |
||||||
520 | */ |
||||||
521 | $stmt = $this->pdo->prepare($this->query); |
||||||
522 | $result['error'] = !$stmt->execute(); |
||||||
523 | $result['result'] = $stmt->fetchAll(\PDO::FETCH_ASSOC); |
||||||
524 | |||||||
525 | return $result; |
||||||
526 | } |
||||||
527 | |||||||
528 | public function execute(array $value = []) |
||||||
529 | { |
||||||
530 | $result = ['query' => $this->query, 'error' => true]; |
||||||
531 | /** |
||||||
532 | * @var statement |
||||||
533 | */ |
||||||
534 | $stmt = $this->pdo->prepare($this->query); |
||||||
535 | $exec = $stmt->execute($value); |
||||||
536 | if ($exec) { |
||||||
537 | $result['error'] = false; |
||||||
538 | } |
||||||
539 | |||||||
540 | return $result; |
||||||
541 | } |
||||||
542 | |||||||
543 | /** |
||||||
544 | * Automated Executor. |
||||||
545 | * |
||||||
546 | * @return array |
||||||
547 | */ |
||||||
548 | public function exec(array $value = []) |
||||||
549 | { |
||||||
550 | $exec = $this->SQL_Exec($this->trim($this->query), $value); |
||||||
551 | $this->resetQuery(); |
||||||
552 | |||||||
553 | return $exec; |
||||||
554 | } |
||||||
555 | |||||||
556 | public function exec2(array $value) |
||||||
557 | { |
||||||
558 | $result = ['error' => true]; |
||||||
559 | /** |
||||||
560 | * @var EPDOStatement |
||||||
561 | */ |
||||||
562 | $stmt = $this->pdo->prepare($this->query); |
||||||
563 | $bind = []; |
||||||
564 | $i = 0; |
||||||
565 | foreach ($value as $key => $value) { |
||||||
566 | switch (gettype($value)) { |
||||||
567 | case 'int': |
||||||
568 | $type = GlobalPDO::PARAM_INT; |
||||||
569 | break; |
||||||
570 | case 'number': |
||||||
571 | $type = GlobalPDO::PARAM_INT; |
||||||
572 | break; |
||||||
573 | case 'boolean': |
||||||
574 | $type = GlobalPDO::PARAM_BOOL; |
||||||
575 | break; |
||||||
576 | case 'bool': |
||||||
577 | $type = GlobalPDO::PARAM_BOOL; |
||||||
578 | break; |
||||||
579 | |||||||
580 | default: |
||||||
581 | $type = GlobalPDO::PARAM_STR; |
||||||
582 | break; |
||||||
583 | } |
||||||
584 | if (!isset($type)) { |
||||||
585 | throw new Exception('Error Processing Code: var(type) not exists, and value instance of ' . gettype($value), 1); |
||||||
586 | } |
||||||
587 | $bind[$i][$key]['key'] = ":$key"; |
||||||
588 | $bind[$i][$key]['value'] = $value; |
||||||
589 | $bind[$i][$key]['type'] = $type; |
||||||
590 | $stmt->bindValue(":$key", $value, $type); |
||||||
591 | ++$i; |
||||||
592 | } |
||||||
593 | try { |
||||||
594 | $exec = $stmt->execute($value); |
||||||
595 | if ($exec) { |
||||||
596 | $result['error'] = false; |
||||||
597 | } |
||||||
598 | //$user = $stmt->fetch(); |
||||||
599 | } catch (PDOException $e) { |
||||||
600 | $message = "{$e->getMessage()} |
||||||
601 | <br>Code: {$stmt->errorCode()} |
||||||
602 | <br>Info: " . serialize($stmt->errorInfo()); |
||||||
603 | $json = json::json($bind, false, false); |
||||||
604 | if (PDO_DEBUG == 3) { |
||||||
605 | $message .= " |
||||||
606 | <br/>Query: {$this->query} |
||||||
607 | <br/>Callback Query: {$stmt->queryString} |
||||||
608 | <br/>Debug: {$stmt->_debugQuery()} |
||||||
0 ignored issues
–
show
The method
_debugQuery() does not exist on PDOStatement . Are you sure you never get this type here, but always one of the subclasses?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
609 | <br/>{$stmt->debugDumpParams()} |
||||||
610 | <br><pre>{$json}</pre> |
||||||
611 | "; |
||||||
612 | } |
||||||
613 | throw new PDOException($message, (int) $e->getCode()); |
||||||
614 | } |
||||||
615 | } |
||||||
616 | |||||||
617 | public function trim(string $str) |
||||||
618 | { |
||||||
619 | return trim(preg_replace('/\s+/s', ' ', $str)); |
||||||
620 | } |
||||||
621 | |||||||
622 | public function where($is_equals = [], $not_equals = [], $param = null) |
||||||
0 ignored issues
–
show
The parameter
$not_equals is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
623 | { |
||||||
624 | $this->query .= ' WHERE '; |
||||||
625 | if (!empty($is_equals)) { |
||||||
626 | $this->equals($is_equals); |
||||||
627 | } |
||||||
628 | if ($param && empty($param)) { |
||||||
629 | $this->query .= " $param "; |
||||||
630 | } |
||||||
631 | |||||||
632 | return $this; |
||||||
633 | } |
||||||
634 | |||||||
635 | /** |
||||||
636 | * Order by row [ASC=ascending or DESC=descending]. |
||||||
637 | * |
||||||
638 | * @param string $order |
||||||
639 | * |
||||||
640 | * @return $this |
||||||
641 | */ |
||||||
642 | public function sort(array $by, $order = 'ASC') |
||||||
643 | { |
||||||
644 | $this->query .= ' ORDER BY '; |
||||||
645 | for ($i = 0; $i < count($by); ++$i) { |
||||||
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||||||
646 | $this->query .= " {$by[$i]} "; |
||||||
647 | if (!($i == count($by) - 1)) { |
||||||
648 | $this->query .= ','; |
||||||
649 | } |
||||||
650 | } |
||||||
651 | $this->query .= " $order "; |
||||||
652 | |||||||
653 | return $this; |
||||||
654 | } |
||||||
655 | |||||||
656 | public function or($is_equals = [], $not_equals = []) |
||||||
0 ignored issues
–
show
The parameter
$not_equals is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
657 | { |
||||||
658 | $this->query .= ' OR '; |
||||||
659 | if (!empty($is_equals)) { |
||||||
660 | $this->equals($is_equals); |
||||||
661 | } |
||||||
662 | |||||||
663 | return $this; |
||||||
664 | } |
||||||
665 | |||||||
666 | public function and($is_equals = [], $not_equals = []) |
||||||
0 ignored issues
–
show
The parameter
$not_equals is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||||
667 | { |
||||||
668 | $this->query .= ' AND '; |
||||||
669 | if (!empty($is_equals)) { |
||||||
670 | $this->equals($is_equals); |
||||||
671 | } |
||||||
672 | |||||||
673 | return $this; |
||||||
674 | } |
||||||
675 | |||||||
676 | /** |
||||||
677 | * If array data is equals. |
||||||
678 | */ |
||||||
679 | public function equals(array $is_equals) |
||||||
680 | { |
||||||
681 | if (!empty($is_equals)) { |
||||||
682 | $i = count($is_equals); |
||||||
683 | foreach ($is_equals as $key => $value) { |
||||||
684 | if ('NULL' == $value || null === $value) { |
||||||
685 | $this->query .= " `$key` IS NULL "; |
||||||
686 | } elseif ($value) { |
||||||
687 | //$value = "'$value'"; |
||||||
688 | $this->query .= " `$key` = '$value' "; |
||||||
689 | } |
||||||
690 | if ($i > 1) { // if condition more than 1, add AND command |
||||||
691 | $this->query .= ' AND '; |
||||||
692 | } |
||||||
693 | --$i; |
||||||
694 | } |
||||||
695 | } |
||||||
696 | |||||||
697 | return $this; |
||||||
698 | } |
||||||
699 | |||||||
700 | /** |
||||||
701 | * Get query result. |
||||||
702 | * |
||||||
703 | * @todo check before execution |
||||||
704 | * |
||||||
705 | * @return array |
||||||
706 | * |
||||||
707 | * @author Dimas Lanjaka <[email protected]> |
||||||
708 | */ |
||||||
709 | public function getQuery(array $data_value = []) |
||||||
710 | { |
||||||
711 | $query = $this->query; |
||||||
712 | if (!empty($data_value)) { |
||||||
713 | foreach ($data_value as $key => $value) { |
||||||
714 | $query = str_replace(":$key", $this->pdo->quote($value), $this->query); |
||||||
715 | } |
||||||
716 | } |
||||||
717 | |||||||
718 | $query = str_replace("\n", ' ', $query); |
||||||
719 | $this->query = ''; |
||||||
720 | |||||||
721 | return $query; |
||||||
0 ignored issues
–
show
|
|||||||
722 | } |
||||||
723 | |||||||
724 | /** |
||||||
725 | * Get last inserted id. |
||||||
726 | * |
||||||
727 | * @param GlobalPDO $pdo |
||||||
728 | */ |
||||||
729 | public function SQL_LastID() |
||||||
730 | { |
||||||
731 | return $this->pdo->lastInsertId(); |
||||||
732 | } |
||||||
733 | |||||||
734 | /** |
||||||
735 | * PDO Error. |
||||||
736 | * |
||||||
737 | * @param PDOException $e |
||||||
738 | * @param mixed $query |
||||||
739 | */ |
||||||
740 | public function SQL_Error($e, $query = null) |
||||||
741 | { |
||||||
742 | $result = ['error' => true]; |
||||||
743 | if (headers_sent()) { |
||||||
744 | $result[] = '<pre>'; |
||||||
745 | } |
||||||
746 | |||||||
747 | if (defined('PDO_DEBUG')) { |
||||||
748 | if (headers_sent()) { |
||||||
749 | $result[] = 'SQL Error: ' . $e->getMessage() . "\n\n"; |
||||||
750 | } else { |
||||||
751 | $result['message'] = $e->getMessage(); |
||||||
752 | } |
||||||
753 | |||||||
754 | if (PDO_DEBUG >= '2') { |
||||||
755 | if (headers_sent()) { |
||||||
756 | $result[] = "$query\n\n"; |
||||||
757 | } else { |
||||||
758 | $result['query'] = $query; |
||||||
759 | } |
||||||
760 | } |
||||||
761 | |||||||
762 | if (PDO_DEBUG == '3') { |
||||||
763 | // Print details like script name and line. |
||||||
764 | if (headers_sent()) { |
||||||
765 | print_r($e); |
||||||
766 | } else { |
||||||
767 | $result['dump'] = $e; |
||||||
768 | } |
||||||
769 | } |
||||||
770 | } else { |
||||||
771 | if (headers_sent()) { |
||||||
772 | $result[] = 'SQL Error! Please contact the administrator.'; |
||||||
773 | } else { |
||||||
774 | $result['message'] = 'SQL Error! Please contact the administrator.'; |
||||||
775 | } |
||||||
776 | } |
||||||
777 | $result['title'] = __CLASS__ . '::' . __FUNCTION__; |
||||||
778 | |||||||
779 | if (headers_sent()) { |
||||||
780 | $result[] = '</pre>'; |
||||||
781 | echo implode("\n", $result); |
||||||
782 | } else { |
||||||
783 | json::json($result); |
||||||
784 | } |
||||||
785 | |||||||
786 | // Stop on error. |
||||||
787 | exit; |
||||||
0 ignored issues
–
show
|
|||||||
788 | } |
||||||
789 | |||||||
790 | public function SQL_Fetch($query, $values = false) |
||||||
791 | { |
||||||
792 | if (!$this->pdo) { |
||||||
793 | throw new \MVC\Exception('Database not properly configured', 1); |
||||||
794 | } |
||||||
795 | try { |
||||||
796 | if (!$values) { |
||||||
797 | return $this->pdo->query($query)->fetch(); |
||||||
798 | } else { |
||||||
799 | $stmt = $this->pdo->prepare($query); |
||||||
800 | $stmt->execute($values); |
||||||
801 | $arr = $stmt->fetch(); |
||||||
802 | $this->query = $this->parms($query, $values); |
||||||
803 | //var_dump($this->query); |
||||||
804 | $stmt = null; |
||||||
0 ignored issues
–
show
|
|||||||
805 | |||||||
806 | return $arr; |
||||||
807 | } |
||||||
808 | } catch (PDOException $e) { |
||||||
809 | //var_dump('error true'); |
||||||
810 | $this->SQL_Error($e, $query); |
||||||
811 | } |
||||||
812 | } |
||||||
813 | |||||||
814 | /** |
||||||
815 | * Reset auto increment value for max id from it's table |
||||||
816 | * |
||||||
817 | * @param string $tablename |
||||||
818 | * @return void |
||||||
819 | */ |
||||||
820 | public function resetAutoIncrement(string $tablename) |
||||||
821 | { |
||||||
822 | $sql = "SELECT @max := MAX(ID)+ 1 FROM $tablename; |
||||||
823 | PREPARE stmt FROM 'ALTER TABLE $tablename AUTO_INCREMENT = ?'; |
||||||
824 | EXECUTE stmt USING @max; |
||||||
825 | DEALLOCATE PREPARE stmt;"; |
||||||
826 | $this->query($sql)->exec(); |
||||||
827 | } |
||||||
828 | |||||||
829 | /** |
||||||
830 | * Check before insert |
||||||
831 | * * always equals validation. |
||||||
832 | * |
||||||
833 | * @return $this |
||||||
834 | */ |
||||||
835 | public function insert_not_exists(string $tbl, array $data, array $where = null) |
||||||
836 | { |
||||||
837 | $keys = array_keys($data); |
||||||
838 | $vals = array_values($data); |
||||||
839 | $valstr = $keystr = $is_equals = ''; |
||||||
840 | for ($i = 0; $i < count($data); ++$i) { |
||||||
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||||||
841 | $value = $vals[$i]; |
||||||
842 | if (!preg_match('/^\:/s', $value)) { |
||||||
843 | $value = $this->pdo->quote($value); |
||||||
844 | } |
||||||
845 | $keystr .= " `{$keys[$i]}` "; |
||||||
846 | $valstr .= " $value "; |
||||||
847 | $is_equals .= " `{$keys[$i]}`=$value "; |
||||||
848 | if ($i == count($data) - 1) { //last iteration |
||||||
849 | //$keystr .= ')'; |
||||||
850 | //$valstr .= ')'; |
||||||
851 | } else { |
||||||
852 | $keystr .= ', '; |
||||||
853 | $valstr .= ', '; |
||||||
854 | $is_equals .= ' AND '; |
||||||
855 | } |
||||||
856 | } |
||||||
857 | if (null !== $where) { |
||||||
858 | $is_equals = ''; |
||||||
859 | foreach ($where as $key => $value) { |
||||||
860 | $is_equals .= " $key = $value "; |
||||||
861 | } |
||||||
862 | } |
||||||
863 | //var_dump($data); |
||||||
864 | $this->query .= " INSERT INTO $tbl ($keystr) "; |
||||||
865 | $this->query .= " SELECT * FROM (SELECT $valstr) AS tmp |
||||||
866 | WHERE NOT EXISTS ( |
||||||
867 | SELECT $keystr FROM $tbl WHERE $is_equals |
||||||
868 | );"; |
||||||
869 | |||||||
870 | return $this; |
||||||
871 | } |
||||||
872 | |||||||
873 | public function parms($string, $data) |
||||||
874 | { |
||||||
875 | $indexed = $data == array_values($data); |
||||||
876 | foreach ($data as $k => $v) { |
||||||
877 | if (is_string($v)) { |
||||||
878 | $v = "'$v'"; |
||||||
879 | } |
||||||
880 | if ($indexed) { |
||||||
881 | $string = preg_replace('/\?/', $v, $string, 1); |
||||||
882 | } else { |
||||||
883 | $string = str_replace(":$k", $v, $string); |
||||||
884 | } |
||||||
885 | } |
||||||
886 | |||||||
887 | return $string; |
||||||
888 | } |
||||||
889 | |||||||
890 | /** |
||||||
891 | * Get result as array. |
||||||
892 | * |
||||||
893 | * @param mixed $value |
||||||
894 | * @param string $filter filter array by key |
||||||
895 | * |
||||||
896 | * @return array|null |
||||||
897 | */ |
||||||
898 | public function row_array($value = false, $filter = null, bool $unique_filter = false) |
||||||
899 | { |
||||||
900 | $exec = $this->SQL_MultiFetch($this->trim($this->query), $value); |
||||||
901 | $this->query = ''; |
||||||
902 | if ($filter) { |
||||||
903 | if (!empty($exec) && is_array($exec)) { |
||||||
904 | $filtered = array_map(function ($data) use ($filter) { |
||||||
905 | if (isset($data[$filter])) { |
||||||
906 | return $data[$filter]; |
||||||
907 | } |
||||||
908 | |||||||
909 | return $data; |
||||||
910 | }, $exec); |
||||||
911 | if ($unique_filter) { |
||||||
912 | return array_unique($filtered); |
||||||
913 | } |
||||||
914 | |||||||
915 | return $filtered; |
||||||
916 | } |
||||||
917 | } |
||||||
918 | |||||||
919 | if (!empty($exec) && is_array($exec)) { |
||||||
920 | return $exec; |
||||||
921 | } |
||||||
922 | } |
||||||
923 | |||||||
924 | /** |
||||||
925 | * Multi fetch pdo. |
||||||
926 | * |
||||||
927 | * @param bool|array $values |
||||||
928 | * @param bool $assoc always association array return |
||||||
929 | * |
||||||
930 | * @return void|array |
||||||
931 | */ |
||||||
932 | public function SQL_MultiFetch(string $query, $values = false, $assoc = false) |
||||||
933 | { |
||||||
934 | if (!$this->pdo) { |
||||||
935 | throw new \MVC\Exception('Database not properly configured', 1); |
||||||
936 | } |
||||||
937 | try { |
||||||
938 | $stmt = $this->pdo->prepare($query); |
||||||
939 | if (!$values) { |
||||||
940 | $stmt->execute(); |
||||||
941 | } else { |
||||||
942 | $stmt->execute($values); |
||||||
0 ignored issues
–
show
It seems like
$values can also be of type true ; however, parameter $params of PDOStatement::execute() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
943 | } |
||||||
944 | $arr = $stmt->fetchAll(); |
||||||
945 | $stmt = null; |
||||||
0 ignored issues
–
show
|
|||||||
946 | |||||||
947 | if (1 == count($arr) && !$assoc) { |
||||||
948 | $arr = $arr[0]; |
||||||
949 | } |
||||||
950 | |||||||
951 | return $arr; |
||||||
952 | } catch (PDOException $e) { |
||||||
953 | $this->SQL_Error($e, $query); |
||||||
954 | } |
||||||
955 | } |
||||||
956 | |||||||
957 | public function SQL_Exec($query, $values = false) |
||||||
958 | { |
||||||
959 | $result = ['query' => $query, 'error' => false, 'title' => 'Database Management']; |
||||||
960 | try { |
||||||
961 | if (!$values) { |
||||||
962 | $status = $this->pdo->exec($query); |
||||||
963 | //var_dump($status); |
||||||
964 | if (!$status && 00000 != (int) $this->pdo->errorCode()) { |
||||||
965 | $result['error'] = true; |
||||||
966 | $result['code'] = $this->pdo->errorCode(); |
||||||
967 | $result['message'] = $this->pdo->errorInfo(); |
||||||
968 | } |
||||||
969 | } else { |
||||||
970 | $stmt = $this->pdo->prepare($query); |
||||||
971 | $stmt->execute($values); |
||||||
972 | $count = 0 == (int) $stmt->rowCount() ? true : false; |
||||||
973 | $result['error'] = $count; |
||||||
974 | $stmt = null; |
||||||
0 ignored issues
–
show
|
|||||||
975 | } |
||||||
976 | if (preg_match('/^insert/s', strtolower($query))) { |
||||||
977 | $result['id'] = $this->SQL_LastID($this->pdo); |
||||||
0 ignored issues
–
show
The call to
DB\pdo::SQL_LastID() has too many arguments starting with $this->pdo .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||
978 | } |
||||||
979 | } catch (PDOException $e) { |
||||||
980 | $this->SQL_Error($e, $query); |
||||||
981 | } |
||||||
982 | |||||||
983 | return $result; |
||||||
984 | } |
||||||
985 | |||||||
986 | public function show_creation(string $table) |
||||||
987 | { |
||||||
988 | return $this->query("SHOW CREATE TABLE `$table`")->row_array(); |
||||||
989 | } |
||||||
990 | } |
||||||
991 |
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.