Total Complexity | 137 |
Total Lines | 835 |
Duplicated Lines | 0 % |
Changes | 17 | ||
Bugs | 0 | Features | 2 |
Complex classes like mysql often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use mysql, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class mysql { |
||
22 | private static mysqli $connection; |
||
23 | |||
24 | private static bool $auto_process = true; |
||
25 | |||
26 | private static string $db_name = ''; |
||
27 | |||
28 | private static array $default_where = []; |
||
29 | |||
30 | /** |
||
31 | * If you want to use it in standalone mode , you MUST set `auto_process` to `false` |
||
32 | */ |
||
33 | public static function init (string $host = 'localhost', string $username = 'root', string $password = '', string $dbname = '', bool $auto_process = true, int $port = 3306, bool $auto_load = false): void { |
||
34 | self::$auto_process = $auto_process; |
||
35 | self::$db_name = $dbname; |
||
36 | self::$connection = new mysqli($host, $username, $password, $dbname, $port); |
||
37 | if (self::$connection->connect_errno) { |
||
38 | logger::write('SQL connection has problem : ' . self::$connection->connect_error, loggerTypes::ERROR); |
||
39 | throw new bptException('SQL_CONNECTION_PROBLEM'); |
||
40 | } |
||
41 | |||
42 | if (!lock::exist('BPT-MYSQL')) { |
||
43 | self::install($auto_load); |
||
44 | } |
||
45 | } |
||
46 | |||
47 | private static function install (bool $auto_load): void { |
||
48 | if (self::$auto_process) { |
||
49 | self::pureQuery(" |
||
50 | CREATE TABLE `users` |
||
51 | ( |
||
52 | `id` BIGINT(20) NOT NULL, |
||
53 | `username` VARCHAR(32) NULL DEFAULT NULL, |
||
54 | `lang_code` VARCHAR(3) NULL DEFAULT NULL, |
||
55 | `first_active` INT(11) NOT NULL DEFAULT '0', |
||
56 | `last_active` INT(11) NOT NULL DEFAULT '0', |
||
57 | `referral` BIGINT(20) NULL DEFAULT NULL, |
||
58 | `blocked` BOOLEAN NOT NULL DEFAULT FALSE, |
||
59 | `step` VARCHAR(64) NOT NULL DEFAULT 'main', |
||
60 | `value` TEXT NULL DEFAULT NULL, |
||
61 | PRIMARY KEY (`id`) |
||
62 | ) ENGINE = InnoDB;"); |
||
63 | self::pureQuery(' |
||
64 | CREATE TABLE `orders` |
||
65 | ( |
||
66 | `id` INT NOT NULL AUTO_INCREMENT, |
||
67 | `user_id` BIGINT(20) NOT NULL, |
||
68 | `type` VARCHAR(30) NOT NULL, |
||
69 | `amount` DOUBLE(13, 4) NOT NULL, |
||
70 | `description` TEXT NOT NULL, |
||
71 | `extra_info` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL, |
||
72 | PRIMARY KEY (`id`) |
||
73 | ) ENGINE = InnoDB;'); |
||
74 | } |
||
75 | |||
76 | if ($auto_load) { |
||
77 | $allowed_file_names = ['db.sql', 'database.sql', 'mysql.sql', 'tables.sql']; |
||
78 | $mysqli = self::getMysqli(); |
||
79 | $loaded = false; |
||
80 | foreach ($allowed_file_names as $allowed_file_name) { |
||
81 | if (file_exists($allowed_file_name)) { |
||
82 | $mysqli->multi_query(file_get_contents($allowed_file_name)); |
||
83 | while ($mysqli->next_result()){if (!$mysqli->more_results()) break;} |
||
84 | $loaded = true; |
||
85 | } |
||
86 | } |
||
87 | } |
||
88 | |||
89 | if (self::$auto_process || (isset($loaded) && $loaded)) { |
||
90 | lock::set('BPT-MYSQL'); |
||
91 | } |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | * @internal Only for BPT self usage , Don't use it in your source! |
||
96 | */ |
||
97 | public static function process (): void { |
||
98 | if (self::$auto_process) { |
||
99 | if (isset(BPT::$update->message)) { |
||
100 | self::processMessage(BPT::$update->message); |
||
|
|||
101 | } |
||
102 | elseif (isset(BPT::$update->edited_message)) { |
||
103 | self::processMessage(BPT::$update->edited_message); |
||
104 | } |
||
105 | elseif (isset(BPT::$update->callback_query)) { |
||
106 | self::processCallbackQuery(BPT::$update->callback_query); |
||
107 | } |
||
108 | elseif (isset(BPT::$update->inline_query)) { |
||
109 | self::processInlineQuery(BPT::$update->inline_query); |
||
110 | } |
||
111 | elseif (isset(BPT::$update->my_chat_member)) { |
||
112 | self::processMyChatMember(BPT::$update->my_chat_member); |
||
113 | } |
||
114 | } |
||
115 | } |
||
116 | |||
117 | private static function processMessage (message $update): void { |
||
118 | $type = $update->chat->type; |
||
119 | if ($type === chatType::PRIVATE) { |
||
120 | $user_id = $update->from->id; |
||
121 | $first_active = $last_active = time(); |
||
122 | $referral = null; |
||
123 | $username = $update->from->username; |
||
124 | $lang_code = $update->from->language_code; |
||
125 | if (isset($update->command) && isset($update->command_payload) && $update->command === 'start' && str_starts_with($update->command_payload, 'ref_')) { |
||
126 | if (tools::isShorted(substr($update->command_payload, 4))) { |
||
127 | $referral = tools::shortDecode(substr($update->command_payload, 4)); |
||
128 | } |
||
129 | } |
||
130 | self::query('INSERT INTO `users`(`id`, `username`, `lang_code`, `first_active`, `last_active`, `referral`) VALUES (?,?,?,?,?,?) on duplicate key update `last_active` = ?, `username` = ?', [ |
||
131 | $user_id, |
||
132 | $username, |
||
133 | $lang_code, |
||
134 | $first_active, |
||
135 | $last_active, |
||
136 | $referral, |
||
137 | $last_active, |
||
138 | $username |
||
139 | ]); |
||
140 | } |
||
141 | } |
||
142 | |||
143 | private static function processCallbackQuery (callbackQuery $update): void { |
||
144 | $type = $update->message->chat->type; |
||
145 | if ($type === chatType::PRIVATE) { |
||
146 | $user_id = $update->from->id; |
||
147 | $last_active = time(); |
||
148 | $username = $update->from->username; |
||
149 | self::update('users', ['last_active' => $last_active, 'username' => $username], ['id' => $user_id], 1); |
||
150 | } |
||
151 | } |
||
152 | |||
153 | private static function processInlineQuery (inlineQuery $update): void { |
||
154 | $type = $update->chat_type; |
||
155 | if ($type === chatType::PRIVATE || $type === chatType::SENDER) { |
||
156 | $user_id = $update->from->id; |
||
157 | $last_active = time(); |
||
158 | $username = $update->from->username; |
||
159 | self::update('users', ['last_active' => $last_active, 'username' => $username], ['id' => $user_id], 1); |
||
160 | } |
||
161 | } |
||
162 | |||
163 | private static function processMyChatMember (chatMemberUpdated $update): void { |
||
164 | $type = $update->chat->type; |
||
165 | if ($type === chatType::PRIVATE) { |
||
166 | if ($update->new_chat_member->status === chatMemberStatus::MEMBER) { |
||
167 | self::update('users', ['blocked' => false], ['id' => $update->from->id], 1); |
||
168 | } |
||
169 | else { |
||
170 | self::update('users', ['blocked' => true], ['id' => $update->from->id], 1); |
||
171 | } |
||
172 | } |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * Add default where to mysql queries, it will apply on every query automatically |
||
177 | * |
||
178 | * Note : where parameter in each query has more priority and will rewrite if already exist |
||
179 | * |
||
180 | * Note : only builder method support this(methods with where parameter like select, update and ...) |
||
181 | * |
||
182 | * @param array $where |
||
183 | * |
||
184 | * @return bool |
||
185 | */ |
||
186 | public static function addDefaultWhere (array $where): bool { |
||
187 | if (empty(self::$default_where)) { |
||
188 | self::$default_where = $where; |
||
189 | } |
||
190 | else { |
||
191 | self::$default_where = array_merge(self::$default_where, $where); |
||
192 | } |
||
193 | return true; |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * Get real mysqli connections |
||
198 | * |
||
199 | * @return mysqli |
||
200 | */ |
||
201 | public static function getMysqli (): mysqli|false { |
||
202 | return self::$connection ?? false; |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * Get affected rows |
||
207 | * |
||
208 | * same as affectedRows |
||
209 | * |
||
210 | * @return int|string |
||
211 | */ |
||
212 | public static function affected_rows (): int|string { |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * Get affected rows |
||
218 | * |
||
219 | * same as affected_rows |
||
220 | * |
||
221 | * @return int|string |
||
222 | */ |
||
223 | public static function affectedRows (): int|string { |
||
224 | return self::$connection->affected_rows; |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * Get inserted id |
||
229 | * |
||
230 | * same as insertId |
||
231 | * |
||
232 | * @return int|string |
||
233 | */ |
||
234 | public static function insert_id (): int|string { |
||
235 | return self::$connection->insert_id; |
||
236 | } |
||
237 | |||
238 | /** |
||
239 | * Get inserted id |
||
240 | * |
||
241 | * same as insert_id |
||
242 | * |
||
243 | * @return int|string |
||
244 | */ |
||
245 | public static function insertId (): int|string { |
||
246 | return self::$connection->insert_id; |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * Escape string with real_escape_string of mysqli class |
||
251 | * |
||
252 | * @param string $text |
||
253 | * |
||
254 | * @return string |
||
255 | */ |
||
256 | public static function escapeString (string $text): string { |
||
257 | return self::$connection->real_escape_string($text); |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * Get last error |
||
262 | * |
||
263 | * @return string |
||
264 | */ |
||
265 | public static function error (): string { |
||
266 | return self::$connection->error; |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * Get last error code |
||
271 | * |
||
272 | * @return int |
||
273 | */ |
||
274 | public static function errno (): int { |
||
275 | return self::$connection->errno; |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * set database charset |
||
280 | * |
||
281 | * @param string $charset |
||
282 | * |
||
283 | * @return bool |
||
284 | */ |
||
285 | public static function setCharset (string $charset): bool { |
||
286 | return self::$connection->set_charset($charset); |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * Run query as what is it |
||
291 | * |
||
292 | * The library doesn't do anything on it |
||
293 | * |
||
294 | * It's like calling mysqli->query(); |
||
295 | * |
||
296 | * @param string $query |
||
297 | * |
||
298 | * @return mysqli_result|bool |
||
299 | */ |
||
300 | public static function pureQuery (string $query): mysqli_result|bool { |
||
301 | return self::$connection->query($query); |
||
302 | } |
||
303 | |||
304 | /** |
||
305 | * Run query with safe execution |
||
306 | * |
||
307 | * Replace inputs with `?` in query to be replaced safely with $vars in order |
||
308 | * |
||
309 | * it will use `pureQuery` if `$vars` be empty |
||
310 | * |
||
311 | * e.g. : mysql::query('select * from `users` where `id` = ? limit 1',[123456789]); |
||
312 | * |
||
313 | * e.g. : mysql::query('update `users` set `step` = ? where `id` = ? limit 1',['main',123456789]); |
||
314 | * |
||
315 | * @param string $query |
||
316 | * @param array $vars default [] or empty |
||
317 | * @param bool $need_result set if you want result be returned, default : true |
||
318 | * |
||
319 | * @return mysqli_result|bool |
||
320 | */ |
||
321 | public static function query (string $query, array $vars = [], bool $need_result = true): mysqli_result|bool { |
||
322 | if (empty($vars)) { |
||
323 | return self::pureQuery($query); |
||
324 | } |
||
325 | $prepare = self::$connection->prepare($query); |
||
326 | $types = ''; |
||
327 | foreach ($vars as $var) { |
||
328 | if (is_int($var)) { |
||
329 | $types .= 'i'; |
||
330 | } |
||
331 | elseif (is_double($var)) { |
||
332 | $types .= 'd'; |
||
333 | } |
||
334 | else { |
||
335 | $types .= 's'; |
||
336 | } |
||
337 | } |
||
338 | $prepare->bind_param($types,...$vars); |
||
339 | if (!$prepare->execute()) { |
||
340 | logger::write(loggerTypes::WARNING, $prepare->error); |
||
341 | return false; |
||
342 | } |
||
343 | return $need_result ? $prepare->get_result() : true; |
||
344 | } |
||
345 | |||
346 | private static function whereBuilder(string &$query, array $where = [], bool $ignore_default_where = false): array { |
||
347 | if (!$ignore_default_where) { |
||
348 | $where = array_merge(self::$default_where, $where); |
||
349 | } |
||
350 | |||
351 | if (empty($where)) { |
||
352 | return []; |
||
353 | } |
||
354 | |||
355 | $query .= ' WHERE'; |
||
356 | $first = true; |
||
357 | $values = []; |
||
358 | |||
359 | foreach ($where as $name => $value) { |
||
360 | if ($first) { |
||
361 | $first = false; |
||
362 | } |
||
363 | else { |
||
364 | $query .= ' AND'; |
||
365 | } |
||
366 | |||
367 | if (empty($value)) { |
||
368 | $query .= " `$name` = ?"; |
||
369 | $values[] = $value; |
||
370 | continue; |
||
371 | } |
||
372 | |||
373 | if (!is_array($value)) { |
||
374 | $value = [$value]; |
||
375 | } |
||
376 | |||
377 | $sub_first = true; |
||
378 | foreach ($value as $sub_value) { |
||
379 | if ($sub_first) { |
||
380 | $sub_first = false; |
||
381 | } |
||
382 | else { |
||
383 | $query .= ' AND'; |
||
384 | } |
||
385 | $operator = substr($sub_value,0,2); |
||
386 | $operator_value = substr($sub_value,2); |
||
387 | switch ($operator) { |
||
388 | case '>=': |
||
389 | $query .= " `$name` >= ?"; |
||
390 | $sub_value = $operator_value; |
||
391 | break; |
||
392 | case '<=': |
||
393 | $query .= " `$name` <= ?"; |
||
394 | $sub_value = $operator_value; |
||
395 | break; |
||
396 | case '> ': |
||
397 | $query .= " `$name` > ?"; |
||
398 | $sub_value = $operator_value; |
||
399 | break; |
||
400 | case '< ': |
||
401 | $query .= " `$name` < ?"; |
||
402 | $sub_value = $operator_value; |
||
403 | break; |
||
404 | case '% ': |
||
405 | $query .= " `$name` like ?"; |
||
406 | $sub_value = $operator_value; |
||
407 | break; |
||
408 | case '!=': |
||
409 | $query .= " `$name` != ?"; |
||
410 | $sub_value = $operator_value; |
||
411 | break; |
||
412 | case '##': |
||
413 | $operator = substr($operator_value,0,2); |
||
414 | $column = substr($operator_value,2); |
||
415 | $query .= match ($operator) { |
||
416 | '>=' => " `$name` >= `$column`", |
||
417 | '<=' => " `$name` <= `$column`", |
||
418 | '> ' => " `$name` > `$column`", |
||
419 | '< ' => " `$name` < `$column`", |
||
420 | '% ' => " `$name` like `$column`", |
||
421 | '!=' => " `$name` != `$column`", |
||
422 | default => " `$name` = `$column`", |
||
423 | }; |
||
424 | continue 2; |
||
425 | default: |
||
426 | $query .= " `$name` = ?"; |
||
427 | break; |
||
428 | } |
||
429 | |||
430 | $values[] = $sub_value; |
||
431 | } |
||
432 | |||
433 | } |
||
434 | |||
435 | return $values; |
||
436 | } |
||
437 | |||
438 | private static function groupByBuilder(string &$query, string|array $group_by = []): void { |
||
439 | if (empty($group_by)) { |
||
440 | return; |
||
441 | } |
||
442 | if (is_string($group_by)) { |
||
443 | $group_by = [$group_by]; |
||
444 | } |
||
445 | $query .= ' GROUP BY `' . implode('`, `',$group_by) . '`'; |
||
446 | } |
||
447 | |||
448 | private static function orderByBuilder(string &$query, string|array $order_by = []): void { |
||
449 | if (empty($order_by)) { |
||
450 | return; |
||
451 | } |
||
452 | if (is_string($order_by)) { |
||
453 | $order_by = [$order_by => 'ASC']; |
||
454 | } |
||
455 | |||
456 | $query .= ' ORDER BY `'; |
||
457 | |||
458 | $first = true; |
||
459 | foreach ($order_by as $key => $mode) { |
||
460 | if ($first) { |
||
461 | $first = false; |
||
462 | } |
||
463 | else { |
||
464 | $query .= ', '; |
||
465 | } |
||
466 | if (is_numeric($key)) { |
||
467 | $key = $mode; |
||
468 | $mode = 'ASC'; |
||
469 | } |
||
470 | $query .= "$key` $mode"; |
||
471 | } |
||
472 | } |
||
473 | |||
474 | private static function countBuilder(string &$query, int $count = null, int $offset = null): void { |
||
475 | if (!empty($count)) { |
||
476 | $query .= !empty($offset) ? " LIMIT $offset, $count" : " LIMIT $count"; |
||
477 | } |
||
478 | elseif (!empty($offset)) { |
||
479 | $query .= " OFFSET $offset"; |
||
480 | } |
||
481 | } |
||
482 | |||
483 | private static function updateBuilder(string &$query, array $modify): array { |
||
484 | $first = true; |
||
485 | $values = []; |
||
486 | |||
487 | foreach ($modify as $name => $value) { |
||
488 | if ($first) { |
||
489 | $first = false; |
||
490 | } |
||
491 | else { |
||
492 | $query .= ','; |
||
493 | } |
||
494 | |||
495 | if (empty($value)) { |
||
496 | $query .= " `$name` = ?"; |
||
497 | $values[] = $value; |
||
498 | continue; |
||
499 | } |
||
500 | |||
501 | $operator = substr($value,0,2); |
||
502 | $operator_value = substr($value,2); |
||
503 | switch ($operator) { |
||
504 | case '+=': |
||
505 | $query .= " `$name` = `$name` + ?"; |
||
506 | $value = $operator_value; |
||
507 | break; |
||
508 | case '-=': |
||
509 | $query .= " `$name` = `$name` - ?"; |
||
510 | $value = $operator_value; |
||
511 | break; |
||
512 | case '*=': |
||
513 | $query .= " `$name` = `$name` * ?"; |
||
514 | $value = $operator_value; |
||
515 | break; |
||
516 | case '/=': |
||
517 | $query .= " `$name` = `$name` / ?"; |
||
518 | $value = $operator_value; |
||
519 | break; |
||
520 | case '%=': |
||
521 | $query .= " `$name` = `$name` % ?"; |
||
522 | $value = $operator_value; |
||
523 | break; |
||
524 | default: |
||
525 | $query .= " `$name` = ?"; |
||
526 | break; |
||
527 | } |
||
528 | |||
529 | $values[] = $value; |
||
530 | } |
||
531 | |||
532 | return $values; |
||
533 | } |
||
534 | |||
535 | private static function insertBuilder(string &$query, string|array $columns, array|string $values): array { |
||
536 | $query .= '(`' . (is_string($columns) ? $columns : implode('`, `', $columns)) . '`) VALUES ('; |
||
537 | if (is_string($values)) $values = [$values]; |
||
538 | $query .= '?' . str_repeat(', ?', count($values) - 1) . ')'; |
||
539 | return $values; |
||
540 | } |
||
541 | |||
542 | private static function selectBuilder (string &$query, string|array $columns): void { |
||
543 | if ($columns == '*') { |
||
544 | $query .= ' * '; |
||
545 | return; |
||
546 | } |
||
547 | if (is_string($columns)) { |
||
548 | $query .= " `$columns` "; |
||
549 | return; |
||
550 | } |
||
551 | $query .= ' '; |
||
552 | foreach ($columns as $key => $column) { |
||
553 | if (is_array($column)) { |
||
554 | $function = array_key_first($column); |
||
555 | $column = $column[$function]; |
||
556 | $formatted = "`$column`"; |
||
557 | if ($column == '*') { |
||
558 | $formatted = '*'; |
||
559 | $column = 'all'; |
||
560 | } |
||
561 | $query .= strtoupper($function) . "($formatted) as `{$function}_$column`"; |
||
562 | } |
||
563 | else { |
||
564 | $query .= "`$column`"; |
||
565 | } |
||
566 | |||
567 | if ($key != array_key_last($columns)) { |
||
568 | $query .= ', '; |
||
569 | } |
||
570 | } |
||
571 | $query .= ' '; |
||
572 | } |
||
573 | |||
574 | /** |
||
575 | * Run delete query |
||
576 | * |
||
577 | * e.g. : `mysql::delete('users',['id'=>123456789],1);` |
||
578 | * |
||
579 | * @param string $table table name |
||
580 | * @param array $where Set your ifs |
||
581 | * @param int|null $count Set if you want to delete specific amount of row default : null |
||
582 | * @param int|null $offset Set if you want to delete rows after specific row default : null |
||
583 | * @param bool $ignore_default_where |
||
584 | * |
||
585 | * @return bool |
||
586 | */ |
||
587 | public static function delete (string $table, array $where = [], int $count = null, int $offset = null, bool $ignore_default_where = false): bool { |
||
592 | } |
||
593 | |||
594 | /** |
||
595 | * Run update query |
||
596 | * |
||
597 | * e.g. : mysql::update('users',['step'=>'panel'],['id'=>123456789],1); |
||
598 | * |
||
599 | * @param string $table table name |
||
600 | * @param array $modify Set the data's you want to modify |
||
601 | * @param array $where Set your ifs |
||
602 | * @param int|null $count Set if you want to update specific amount of row default : null |
||
603 | * @param int|null $offset Set if you want to update rows after specific row default : null |
||
604 | * @param bool $ignore_default_where |
||
605 | * |
||
606 | * @return bool |
||
607 | */ |
||
608 | public static function update (string $table, array $modify, array $where = [], int $count = null, int $offset = null, bool $ignore_default_where = false): bool { |
||
609 | $query = "UPDATE `$table` SET"; |
||
610 | $modify_vars = self::updateBuilder($query, $modify); |
||
611 | $where_vars = self::whereBuilder($query, $where, $ignore_default_where); |
||
612 | self::countBuilder($query, $count, $offset); |
||
613 | return self::query($query, array_merge($modify_vars, $where_vars), false); |
||
614 | } |
||
615 | |||
616 | /** |
||
617 | * Run insert query |
||
618 | * |
||
619 | * e.g. : `mysql::insert('users',['id','column1','column2','column3'],[123456789,'value1','value2','value3']);` |
||
620 | * |
||
621 | * @param string $table table name |
||
622 | * @param string|array $columns sets columns that you want to fill |
||
623 | * @param array|string $values sets value that you want to set |
||
624 | * |
||
625 | * @return bool |
||
626 | */ |
||
627 | public static function insert (string $table, string|array $columns, array|string $values): bool { |
||
631 | } |
||
632 | |||
633 | /** |
||
634 | * Run insert query |
||
635 | * |
||
636 | * e.g. : `mysql::multiInsert('users', ['id' => 123, 'name' => 'qwe'], ['id' => 234, 'name' => 'wer'], ['name' => 'ert', 'id' => 345]]);` |
||
637 | * |
||
638 | * @param string $table table name |
||
639 | * @param array ...$inserts ['column_name' => 'value', 'column_name2' => 'value2'] |
||
640 | * |
||
641 | * @return bool |
||
642 | */ |
||
643 | public static function multiInsert (string $table, array ...$inserts): bool { |
||
644 | $all_letters = true; |
||
645 | foreach ($inserts as $insert) { |
||
646 | foreach ($insert as $column => $value) { |
||
647 | if (!is_string($column)) { |
||
648 | $all_letters = false; |
||
649 | break 2; |
||
650 | } |
||
651 | } |
||
652 | } |
||
653 | $columns = array_keys($inserts[0]); |
||
654 | if ($all_letters) { |
||
655 | sort($columns); |
||
656 | } |
||
657 | $query = "INSERT INTO `$table`(`" . '' . (is_string($columns) ? $columns : implode('`, `', $columns)) . '`) VALUES'; |
||
658 | |||
659 | $all_values = []; |
||
660 | foreach ($inserts as $key => $insert) { |
||
661 | if ($all_letters) { |
||
662 | asort($insert); |
||
663 | } |
||
664 | $values = array_values($insert); |
||
665 | $query .= ($key != 0 ? ',' : '') . ' (?' . str_repeat(', ?', count($values) - 1) . ')'; |
||
666 | $all_values = array_merge($all_values, $values); |
||
667 | } |
||
668 | return self::query($query, $all_values, false); |
||
669 | } |
||
670 | |||
671 | /** |
||
672 | * Run insert query with update on duplicate key |
||
673 | * |
||
674 | * These kind of query need to act on a key(primary key, unique key, ...) |
||
675 | * |
||
676 | * So your table must have a key column and your query must use it somehow(in insert part) |
||
677 | * |
||
678 | * e.g.(date is our key) : `mysql::insertUpdate('stats', ['date', 'new_users'], ['2020/04/08', 1], ['new_users' => '+=1']);` |
||
679 | * |
||
680 | * |
||
681 | * @param string $table table name |
||
682 | * @param string|array $columns sets columns that you want to fill |
||
683 | * @param array|string $values sets value that you want to set |
||
684 | * @param array $modify Set the data's you want to modify |
||
685 | * |
||
686 | * @return bool |
||
687 | */ |
||
688 | public static function insertUpdate (string $table, string|array $columns, array|string $values, array $modify): bool { |
||
689 | $query = "INSERT INTO `$table`"; |
||
690 | $values = self::insertBuilder($query, $columns, $values); |
||
691 | $query .= ' ON DUPLICATE KEY UPDATE'; |
||
692 | $modify_vars = self::updateBuilder($query, $modify); |
||
693 | return self::query($query, array_merge($values, $modify_vars), false); |
||
694 | } |
||
695 | |||
696 | /** |
||
697 | * Run select query |
||
698 | * |
||
699 | * e.g. : mysql::select('users','*',['id'=>123456789],1); |
||
700 | * |
||
701 | * e.g. : mysql::select('users',['step','referrals'],['id'=>123456789],1); |
||
702 | * |
||
703 | * @param string $table table name |
||
704 | * @param array|string $columns sets column that you want to retrieve , set '*' to retrieve all , default : '*' |
||
705 | * @param array $where Set your ifs |
||
706 | * @param int|null $count Set if you want to select specific amount of row default : null |
||
707 | * @param int|null $offset Set if you want to select rows after specific row default : null |
||
708 | * @param array|string $group_by group result based on these columns |
||
709 | * @param array|string $order_by order result based on these columns |
||
710 | * @param bool $ignore_default_where |
||
711 | * |
||
712 | * @return mysqli_result|bool |
||
713 | */ |
||
714 | public static function select (string $table, array|string $columns = '*', array $where = [], int $count = null, int $offset = null, array|string $group_by = [], array|string $order_by = [], bool $ignore_default_where = false): mysqli_result|bool { |
||
715 | $query = 'SELECT'; |
||
716 | self::selectBuilder($query, $columns); |
||
717 | $query .= "FROM `$table`"; |
||
718 | $var = self::whereBuilder($query,$where, $ignore_default_where); |
||
719 | self::groupByBuilder($query, $group_by); |
||
720 | self::orderByBuilder($query, $order_by); |
||
721 | self::countBuilder($query,$count,$offset); |
||
722 | return self::query($query, $var); |
||
723 | } |
||
724 | |||
725 | /** |
||
726 | * Same as mysql::select but return first result as array |
||
727 | * |
||
728 | * mysql::selectArray('users','*',['id'=>123456789]); |
||
729 | * |
||
730 | * @param string $table table name |
||
731 | * @param array|string $columns sets column that you want to retrieve , set '*' to retrieve all , default : '*' |
||
732 | * @param array $where Set your ifs |
||
733 | * @param array|string $group_by group result based on these columns |
||
734 | * @param array|string $order_by order result based on these columns |
||
735 | * @param bool $ignore_default_where |
||
736 | * |
||
737 | * @return null|bool|array |
||
738 | */ |
||
739 | public static function selectArray (string $table, array|string $columns = '*', array $where = [], array|string $group_by = [], array|string $order_by = [], bool $ignore_default_where = false): bool|array|null { |
||
740 | $res = self::select($table, $columns, $where, 1, 0, $group_by, $order_by, ignore_default_where: $ignore_default_where); |
||
741 | if ($res) { |
||
742 | return $res->fetch_assoc(); |
||
743 | } |
||
744 | return $res; |
||
745 | } |
||
746 | |||
747 | /** |
||
748 | * Same as mysql::select but return first result as object(stdClass) |
||
749 | * |
||
750 | * mysql::selectObject('users','*',['id'=>123456789]); |
||
751 | * |
||
752 | * @param string $table table name |
||
753 | * @param array|string $columns sets column that you want to retrieve , set '*' to retrieve all , default : '*' |
||
754 | * @param array $where Set your ifs |
||
755 | * @param array|string $group_by group result based on these columns |
||
756 | * @param array|string $order_by order result based on these columns |
||
757 | * @param bool $ignore_default_where |
||
758 | * |
||
759 | * @return null|object |
||
760 | */ |
||
761 | public static function selectObject (string $table, array|string $columns = '*', array $where = [], array|string $group_by = [], array|string $order_by = [], bool $ignore_default_where = false) { |
||
762 | $res = self::select($table, $columns, $where, 1, 0, $group_by, $order_by, ignore_default_where: $ignore_default_where); |
||
763 | if ($res) { |
||
764 | return $res->fetch_object(); |
||
765 | } |
||
766 | return $res; |
||
767 | } |
||
768 | |||
769 | /** |
||
770 | * Same as mysql::select but return each row as generator |
||
771 | * |
||
772 | * e.g. : mysql::selectEach('users','*',['id'=>123456789],1); |
||
773 | * e.g. : mysql::selectEach('users',['id']); |
||
774 | * |
||
775 | * @param string $table table name |
||
776 | * @param array|string $columns sets column that you want to retrieve , set '*' to retrieve all , default : '*' |
||
777 | * @param array $where Set your ifs |
||
778 | * @param int|null $count Set if you want to select specific amount of row default : null |
||
779 | * @param int|null $offset Set if you want to select rows after specific row default : null |
||
780 | * @param array|string $group_by group result based on these columns |
||
781 | * @param array|string $order_by order result based on these columns |
||
782 | * @param bool $ignore_default_where |
||
783 | * |
||
784 | * @return bool|Generator |
||
785 | */ |
||
786 | public static function selectEach (string $table, array|string $columns = '*', array $where = [], int $count = null, int $offset = null, array|string $group_by = [], array|string $order_by = [], bool $ignore_default_where = false): bool|Generator { |
||
787 | $res = self::select($table, $columns, $where, $count, $offset, $group_by, $order_by, ignore_default_where: $ignore_default_where); |
||
788 | if ($res) { |
||
789 | while ($row = $res->fetch_assoc()) yield $row; |
||
790 | } |
||
791 | else return $res; |
||
792 | } |
||
793 | |||
794 | /** |
||
795 | * get backup from database, you can get full backup or specific table backup |
||
796 | * |
||
797 | * @param array $wanted_tables set if you want specific table which exist |
||
798 | * @param bool $table_data set false if you only want the creation queries(no data) |
||
799 | * @param bool $save set false if you want to receive sql as string |
||
800 | * @param string $file_name file name for saving |
||
801 | * |
||
802 | * @return string if save is true , return file name otherwise return sql data |
||
803 | */ |
||
804 | public static function backup (array $wanted_tables = [], bool $table_data = true, bool $save = true, string $file_name = ''): string { |
||
856 | } |
||
857 | } |