1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | namespace Compolomus\Mysqli; |
||
6 | |||
7 | use mysqli; |
||
8 | use mysqli_driver; |
||
9 | use mysqli_stmt; |
||
10 | |||
11 | class Wrapper |
||
12 | { |
||
13 | public const FETCHTOARRAY = 0; |
||
14 | |||
15 | public const FETCHTOOBJECT = 1; |
||
16 | |||
17 | private mysqli $mysqli; |
||
18 | |||
19 | private ?mysqli_stmt $stmt = null; |
||
20 | |||
21 | 10 | public function __construct(mysqli $mysqli) |
|
22 | { |
||
23 | 10 | $this->mysqli = $mysqli; |
|
24 | 10 | $driver = new mysqli_driver(); |
|
25 | 10 | $driver->report_mode = MYSQLI_REPORT_STRICT; |
|
26 | 10 | } |
|
27 | |||
28 | 8 | public function query(string $query, ?array $placeholders = null) |
|
29 | { |
||
30 | 8 | $this->stmt = $this->mysqli->prepare($query); |
|
31 | |||
32 | 8 | if ($placeholders && $this->countParams() === count($placeholders)) { |
|
33 | 4 | $this->bindParam($placeholders); |
|
34 | } |
||
35 | |||
36 | 8 | $this->stmt->execute(); |
|
37 | |||
38 | 8 | if (!$this->isFetch($query)) { |
|
39 | 4 | return $this->stmt->affected_rows; |
|
40 | } |
||
41 | |||
42 | 4 | if ($placeholders) { |
|
43 | 2 | $this->bindResult(); |
|
44 | } |
||
45 | |||
46 | 4 | return $this; |
|
47 | } |
||
48 | |||
49 | 4 | public function result($mode = self::FETCHTOARRAY) |
|
50 | { |
||
51 | 4 | $data = []; |
|
52 | 4 | $method = $mode ? 'fetch_object' : 'fetch_assoc'; |
|
53 | |||
54 | 4 | $x = 0; |
|
55 | 4 | $res = $this->stmt->get_result(); |
|
56 | 4 | while ($row = $res->$method()) { |
|
57 | 4 | $data[] = $row; |
|
58 | 4 | $x++; |
|
59 | } |
||
60 | |||
61 | 4 | return $this->count_fields() === 1 && $x === 1 ? array_values($data[0])[0] : $data; |
|
62 | } |
||
63 | |||
64 | 2 | private function bindResult(): void |
|
65 | { |
||
66 | 2 | call_user_func_array([$this->stmt, 'bind_result'], $this->getMeta()); |
|
67 | 2 | } |
|
68 | |||
69 | 2 | private function getMeta(): array |
|
70 | { |
||
71 | 2 | $binds = []; |
|
72 | 2 | $meta = $this->stmt->result_metadata(); |
|
73 | 2 | while ($field = $meta->fetch_field()) { |
|
74 | 2 | $binds[] = &$row[$field->name]; |
|
75 | } |
||
76 | |||
77 | 2 | return $binds; |
|
78 | } |
||
79 | |||
80 | 4 | private function bindParam(array $placeholders): void |
|
81 | { |
||
82 | 4 | @call_user_func([$this->stmt, 'bind_param'], $this->placeholdersTypes($placeholders), ...$placeholders); |
|
0 ignored issues
–
show
|
|||
83 | 4 | } |
|
84 | |||
85 | 4 | private function placeholdersTypes(array $placeholders): string |
|
86 | { |
||
87 | 4 | return implode('', array_map([$this, 'types'], $placeholders)); |
|
88 | } |
||
89 | |||
90 | 4 | private function types($value): string |
|
91 | { |
||
92 | 4 | return is_numeric($value) |
|
93 | 4 | ? (is_float($value) ? 'd' : 'i') // int or float |
|
94 | 4 | : (strlen((string)$value) <= 65536 ? 's' : 'b'); // string or blob |
|
95 | } |
||
96 | |||
97 | 4 | private function countParams(): int |
|
98 | { |
||
99 | 4 | return $this->stmt->param_count; |
|
100 | } |
||
101 | |||
102 | 8 | private function isFetch(string $query): bool |
|
103 | { |
||
104 | 8 | return false !== stripos($query, 'select'); |
|
105 | } |
||
106 | |||
107 | 4 | private function count_fields(): int |
|
108 | { |
||
109 | 4 | return $this->stmt->field_count; |
|
110 | } |
||
111 | } |
||
112 |
If you suppress an error, we recommend checking for the error condition explicitly: