1 | <?php |
||||
2 | /** |
||||
3 | * MySQL Related Functionality |
||||
4 | * @author Joe Huss <[email protected]> |
||||
5 | * @copyright 2025 |
||||
6 | * @package MyAdmin |
||||
7 | * @category SQL |
||||
8 | */ |
||||
9 | |||||
10 | namespace MyDb\Mysqli; |
||||
11 | |||||
12 | use MyDb\Generic; |
||||
13 | use MyDb\Db_Interface; |
||||
14 | |||||
15 | /** |
||||
16 | * Db |
||||
17 | * |
||||
18 | * @access public |
||||
19 | */ |
||||
20 | class Db extends Generic implements Db_Interface |
||||
21 | { |
||||
22 | /** |
||||
23 | * @var string |
||||
24 | */ |
||||
25 | public $type = 'mysqli'; |
||||
26 | public $statement; |
||||
27 | public $statement_query; |
||||
28 | public $statement_vars; |
||||
29 | |||||
30 | /** |
||||
31 | * alias function of select_db, changes the database we are working with. |
||||
32 | * |
||||
33 | 1 | * @param string $database the name of the database to use |
|||
34 | * @return void |
||||
35 | 1 | */ |
|||
36 | public function useDb($database) |
||||
37 | { |
||||
38 | $this->selectDb($database); |
||||
39 | } |
||||
40 | |||||
41 | /** |
||||
42 | * changes the database we are working with. |
||||
43 | * |
||||
44 | 1 | * @param string $database the name of the database to use |
|||
45 | * @return void |
||||
46 | 1 | */ |
|||
47 | 1 | public function selectDb($database) |
|||
48 | { |
||||
49 | $this->connect(); |
||||
50 | mysqli_select_db($this->linkId, $database); |
||||
51 | } |
||||
52 | |||||
53 | /* public: connection management */ |
||||
54 | |||||
55 | /** |
||||
56 | * Db::connect() |
||||
57 | * @param string $database |
||||
58 | * @param string $host |
||||
59 | * @param string $user |
||||
60 | 26 | * @param string $password |
|||
61 | * @return int|\mysqli |
||||
62 | */ |
||||
63 | 26 | public function connect($database = '', $host = '', $user = '', $password = '', $port = '') |
|||
64 | 26 | { |
|||
65 | /* Handle defaults */ |
||||
66 | 26 | if ($database == '') { |
|||
67 | 26 | $database = $this->database; |
|||
68 | } |
||||
69 | 26 | if ($host == '') { |
|||
70 | 26 | $host = $this->host; |
|||
71 | } |
||||
72 | 26 | if ($user == '') { |
|||
73 | 26 | $user = $this->user; |
|||
74 | } |
||||
75 | 26 | if ($password == '') { |
|||
76 | 26 | $password = $this->password; |
|||
77 | } |
||||
78 | if ($port == '') { |
||||
79 | 26 | $port = $this->port; |
|||
80 | 26 | } |
|||
81 | 26 | /* establish connection, select database */ |
|||
82 | 6 | if (!is_object($this->linkId)) { |
|||
83 | $this->connectionAttempt++; |
||||
84 | 26 | if ($this->connectionAttempt >= $this->maxConnectErrors - 1) { |
|||
85 | error_log("MySQLi Connection Attempt #{$this->connectionAttempt}/{$this->maxConnectErrors}"); |
||||
86 | exit; |
||||
0 ignored issues
–
show
|
|||||
87 | } |
||||
88 | 26 | if ($this->connectionAttempt >= $this->maxConnectErrors) { |
|||
89 | 26 | $this->halt("connect($host, $user, \$password) failed. ".(is_object($this->linkId) && isset( $this->linkId->connect_error) ? $this->linkId->connect_error : '')); |
|||
0 ignored issues
–
show
|
|||||
90 | 26 | return 0; |
|||
91 | } |
||||
92 | //error_log("real_connect($host, $user, $password, $database, $port)"); |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
80% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||||
93 | 26 | $this->linkId = mysqli_init(); |
|||
94 | $this->linkId->options(MYSQLI_INIT_COMMAND, "SET NAMES {$this->characterSet} COLLATE {$this->collation}, COLLATION_CONNECTION = {$this->collation}, COLLATION_DATABASE = {$this->collation}"); |
||||
95 | 26 | if (!$this->linkId->real_connect($host, $user, $password, $database, $port != '' ? $port : NULL)) { |
|||
96 | 26 | $this->halt("connect($host, $user, \$password) failed. ".(is_object($this->linkId) && isset( $this->linkId->connect_error) ? $this->linkId->connect_error : '')); |
|||
97 | return 0; |
||||
98 | } |
||||
99 | $this->linkId->set_charset($this->characterSet); |
||||
100 | if ($this->linkId->connect_errno) { |
||||
101 | 26 | $this->halt("connect($host, $user, \$password) failed. ".(is_object($this->linkId) && isset( $this->linkId->connect_error) ? $this->linkId->connect_error : '')); |
|||
102 | return 0; |
||||
103 | } |
||||
104 | } |
||||
105 | return $this->linkId; |
||||
106 | } |
||||
107 | |||||
108 | 1 | /** |
|||
109 | * Db::disconnect() |
||||
110 | 1 | * @return bool |
|||
111 | 1 | */ |
|||
112 | 1 | public function disconnect() |
|||
113 | { |
||||
114 | $return = !is_int($this->linkId) && method_exists($this->linkId, 'close') ? $this->linkId->close() : false; |
||||
115 | $this->linkId = 0; |
||||
116 | return $return; |
||||
117 | } |
||||
118 | |||||
119 | 2 | /** |
|||
120 | * @param $string |
||||
121 | 2 | * @return string |
|||
122 | */ |
||||
123 | public function real_escape($string = '') |
||||
124 | 2 | { |
|||
125 | if ((!is_resource($this->linkId) || $this->linkId == 0) && !$this->connect()) { |
||||
0 ignored issues
–
show
|
|||||
126 | return $this->escape($string); |
||||
127 | } |
||||
128 | return mysqli_real_escape_string($this->linkId, $string); |
||||
0 ignored issues
–
show
It seems like
$this->linkId can also be of type integer and resource ; however, parameter $mysql of mysqli_real_escape_string() does only seem to accept mysqli , 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
![]() |
|||||
129 | } |
||||
130 | |||||
131 | 1 | /** |
|||
132 | * discard the query result |
||||
133 | 1 | * @return void |
|||
134 | */ |
||||
135 | public function free() |
||||
136 | 1 | { |
|||
137 | if (is_resource($this->queryId)) { |
||||
0 ignored issues
–
show
|
|||||
138 | @mysqli_free_result($this->queryId); |
||||
0 ignored issues
–
show
It seems like you do not handle an error condition for
mysqli_free_result() . This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||||
139 | } |
||||
140 | $this->queryId = 0; |
||||
141 | } |
||||
142 | |||||
143 | /** |
||||
144 | * Db::queryReturn() |
||||
145 | * |
||||
146 | * Sends an SQL query to the server like the normal query() command but iterates through |
||||
147 | * any rows and returns the row or rows immediately or FALSE on error |
||||
148 | * |
||||
149 | * @param mixed $query SQL Query to be used |
||||
150 | 1 | * @param string $line optionally pass __LINE__ calling the query for logging |
|||
151 | * @param string $file optionally pass __FILE__ calling the query for logging |
||||
152 | 1 | * @return mixed FALSE if no rows, if a single row it returns that, if multiple it returns an array of rows, associative responses only |
|||
153 | 1 | */ |
|||
154 | 1 | public function queryReturn($query, $line = '', $file = '') |
|||
155 | 1 | { |
|||
156 | 1 | $this->query($query, $line, $file); |
|||
0 ignored issues
–
show
$line of type string is incompatible with the type integer expected by parameter $line of MyDb\Mysqli\Db::query() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
157 | 1 | if ($this->num_rows() == 0) { |
|||
158 | return false; |
||||
159 | 1 | } elseif ($this->num_rows() == 1) { |
|||
160 | 1 | $this->next_record(MYSQLI_ASSOC); |
|||
161 | 1 | return $this->Record; |
|||
162 | } else { |
||||
163 | 1 | $out = []; |
|||
164 | while ($this->next_record(MYSQLI_ASSOC)) { |
||||
165 | $out[] = $this->Record; |
||||
166 | } |
||||
167 | return $out; |
||||
168 | } |
||||
169 | } |
||||
170 | |||||
171 | /** |
||||
172 | * db:qr() |
||||
173 | * |
||||
174 | * alias of queryReturn() |
||||
175 | * |
||||
176 | * @param mixed $query SQL Query to be used |
||||
177 | 1 | * @param string $line optionally pass __LINE__ calling the query for logging |
|||
178 | * @param string $file optionally pass __FILE__ calling the query for logging |
||||
179 | 1 | * @return mixed FALSE if no rows, if a single row it returns that, if multiple it returns an array of rows, associative responses only |
|||
180 | */ |
||||
181 | public function qr($query, $line = '', $file = '') |
||||
182 | { |
||||
183 | return $this->queryReturn($query, $line, $file); |
||||
184 | } |
||||
185 | |||||
186 | /** |
||||
187 | * creates a prepaired statement from query |
||||
188 | * |
||||
189 | * @param string $query sql query like INSERT INTO table (col) VALUES (?) or SELECT * from table WHERE col1 = ? and col2 = ? or UPDATE table SET col1 = ?, col2 = ? WHERE col3 = ? |
||||
190 | 1 | * @return false|mysqli_stmt |
|||
0 ignored issues
–
show
|
|||||
191 | * @param string $line |
||||
192 | 1 | * @param string $file |
|||
193 | */ |
||||
194 | public function prepare($query, $line = '', $file = '') |
||||
195 | 1 | { |
|||
196 | 1 | if (!$this->connect()) { |
|||
197 | 1 | return 0; |
|||
198 | 1 | } |
|||
199 | 1 | $haltPrev = $this->haltOnError; |
|||
0 ignored issues
–
show
|
|||||
200 | 1 | $this->haltOnError = 'no'; |
|||
201 | $start = microtime(true); |
||||
202 | $this->statement = mysqli_prepare($this->linkId, $query); |
||||
203 | if (!isset($GLOBALS['disable_db_queries'])) { |
||||
204 | $this->statement_query = $query; |
||||
205 | $this->addLog($query, microtime(true) - $start, $line, $file); |
||||
206 | } |
||||
207 | return $this->statement; |
||||
208 | } |
||||
209 | |||||
210 | /** |
||||
211 | * Binds variables to a prepared statement as parameters |
||||
212 | * |
||||
213 | 10 | * @param string $types A string that contains one or more characters which specify the types for the corresponding bind variables: (i)nt, (d)ecimal, (s)tring, (b)inary |
|||
214 | * @param mixed $vars |
||||
215 | * @return bool indicates success |
||||
216 | */ |
||||
217 | public function bind_param($types, &...$vars) { |
||||
218 | $params = [$this->statement, $types]; |
||||
219 | foreach ($vars as &$var) { |
||||
220 | 10 | $params[] = &$var; // Ensure they stay references |
|||
221 | 1 | } |
|||
222 | if (!isset($GLOBALS['disable_db_queries'])) { |
||||
223 | 10 | $this->statement_vars &= $vars; |
|||
224 | } |
||||
225 | return call_user_func_array('mysqli_stmt_bind_param', $params); |
||||
226 | } |
||||
227 | 10 | ||||
228 | 10 | /** |
|||
229 | * Executes a prepared statement |
||||
230 | 10 | * |
|||
231 | * @return bool success |
||||
232 | */ |
||||
233 | 10 | public function execute($line = '', $file = '') { |
|||
234 | 1 | $start = microtime(true); |
|||
235 | $return = mysqli_stmt_execute($this->statement); |
||||
236 | 10 | if (!isset($GLOBALS['disable_db_queries'])) { |
|||
237 | $vars = $this->statement_vars; |
||||
238 | $query = $result = preg_replace_callback('/\?/', function () use (&$vars) { |
||||
0 ignored issues
–
show
|
|||||
239 | 10 | return array_shift($vars); |
|||
240 | 10 | }, $this->statement_query); |
|||
241 | 10 | $this->addLog($query, microtime(true) - $start, $line, $file); |
|||
242 | 10 | } |
|||
243 | 10 | return $return; |
|||
244 | 10 | } |
|||
245 | |||||
246 | /** |
||||
247 | * Db::query() |
||||
248 | 10 | * |
|||
249 | 10 | * Sends an SQL query to the database |
|||
250 | 10 | * |
|||
251 | 10 | * @param mixed $queryString |
|||
252 | * @param int $line |
||||
253 | * @param string $file |
||||
254 | * @param bool $log |
||||
255 | * @return mixed 0 if no query or query id handler, safe to ignore this return |
||||
256 | */ |
||||
257 | public function query($queryString, $line = '', $file = '', $log = false) |
||||
258 | 10 | { |
|||
259 | /* No empty queries, please, since PHP4 chokes on them. */ |
||||
260 | /* The empty query string is passed on from the constructor, |
||||
261 | 10 | * when calling the class without a query, e.g. in situations |
|||
262 | 10 | * like these: '$db = new db_Subclass;' |
|||
263 | 10 | */ |
|||
264 | 10 | if ($queryString == '') { |
|||
265 | 10 | return 0; |
|||
266 | } |
||||
267 | if (!$this->connect()) { |
||||
268 | return 0; |
||||
269 | 10 | /* we already complained in connect() about that. */ |
|||
270 | 10 | } |
|||
271 | $haltPrev = $this->haltOnError; |
||||
272 | $this->haltOnError = 'no'; |
||||
273 | // New query, discard previous result. |
||||
274 | if (is_resource($this->queryId)) { |
||||
275 | 10 | $this->free(); |
|||
276 | } |
||||
277 | if ($this->Debug) { |
||||
278 | printf("Debug: query = %s<br>\n", $queryString); |
||||
279 | } |
||||
280 | if ($log === true || (isset($GLOBALS['log_queries']) && $GLOBALS['log_queries'] !== false)) { |
||||
281 | 1 | $this->log($queryString, $line, $file); |
|||
282 | } |
||||
283 | 1 | $tries = 2; |
|||
284 | 1 | $try = 0; |
|||
285 | $this->queryId = false; |
||||
286 | while ((null === $this->queryId || $this->queryId === false) && $try <= $tries) { |
||||
287 | $try++; |
||||
288 | if ($try > 1) { |
||||
289 | @mysqli_close($this->linkId); |
||||
0 ignored issues
–
show
It seems like you do not handle an error condition for
mysqli_close() . This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||||
290 | $this->linkId = 0; |
||||
291 | } |
||||
292 | $start = microtime(true); |
||||
293 | $onlyRollback = true; |
||||
294 | $fails = -1; |
||||
295 | 6 | while ($fails < 30 && (null === $this->queryId || $this->queryId === false)) { |
|||
296 | $this->connect(); |
||||
297 | 6 | $fails++; |
|||
298 | try { |
||||
299 | $this->queryId = @mysqli_query($this->linkId, $queryString, MYSQLI_STORE_RESULT); |
||||
300 | if (in_array((int)@mysqli_errno($this->linkId), [1213, 2006, 3101, 1180])) { |
||||
301 | //error_log("got ".@mysqli_errno($this->linkId)." sql error fails {$fails} on query {$queryString} from {$line}:{$file}"); |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
67% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||||
302 | 6 | usleep(250000); // 0.25 second |
|||
303 | 6 | } else { |
|||
304 | 6 | $onlyRollback = false; |
|||
305 | 6 | if (in_array((int)@mysqli_errno($this->linkId), [1064])) { |
|||
306 | $tries = 0; |
||||
307 | 6 | } |
|||
308 | 6 | break; |
|||
309 | } |
||||
310 | } catch (\mysqli_sql_exception $e) { |
||||
311 | 6 | if (in_array((int)$e->getCode(), [1213, 2006, 3101, 1180])) { |
|||
312 | //error_log("got ".$e->getCode()." sql error fails {$fails}"); |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
70% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||||
313 | usleep(250000); // 0.25 second |
||||
314 | } else { |
||||
315 | error_log('Got mysqli_sql_exception code '.$e->getCode().' error '.$e->getMessage().' on query '.$queryString.' from '.$line.':'.$file); |
||||
316 | $onlyRollback = false; |
||||
317 | if (in_array((int)@mysqli_errno($this->linkId), [1064])) { |
||||
318 | $tries = 0; |
||||
319 | } |
||||
320 | 1 | break; |
|||
321 | } |
||||
322 | 1 | } |
|||
323 | 1 | } |
|||
324 | 1 | if (!isset($GLOBALS['disable_db_queries'])) { |
|||
325 | $this->addLog($queryString, microtime(true) - $start, $line, $file); |
||||
326 | 1 | } |
|||
327 | $this->Row = 0; |
||||
328 | 1 | $this->Errno = @mysqli_errno($this->linkId); |
|||
329 | 1 | $this->Error = @mysqli_error($this->linkId); |
|||
330 | 1 | if ($try == 1 && (null === $this->queryId || $this->queryId === false)) { |
|||
0 ignored issues
–
show
This
if statement is empty and can be removed.
This check looks for the bodies of These if (rand(1, 6) > 3) {
//print "Check failed";
} else {
print "Check succeeded";
}
could be turned into if (rand(1, 6) <= 3) {
print "Check succeeded";
}
This is much more concise to read. ![]() |
|||||
331 | 1 | //$this->emailError($queryString, 'Error #'.$this->Errno.': '.$this->Error, $line, $file); |
|||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
66% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||||
332 | } |
||||
333 | 1 | } |
|||
334 | $this->haltOnError = $haltPrev; |
||||
335 | if ($onlyRollback === true && false === $this->queryId) { |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
336 | error_log('Got MySQLi 3101 Rollback Error '.$fails.' Times, Giving Up on '.$queryString.' from '.$line.':'.$file.' on '.__LINE__.':'.__FILE__); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
337 | } |
||||
338 | if (null === $this->queryId || $this->queryId === false) { |
||||
339 | $this->emailError($queryString, 'Error #'.$this->Errno.': '.$this->Error, $line, $file); |
||||
340 | $this->halt('', $line, $file); |
||||
341 | 26 | } |
|||
342 | |||||
343 | 26 | // Will return nada if it fails. That's fine. |
|||
344 | return $this->queryId; |
||||
345 | } |
||||
346 | 26 | ||||
347 | /** |
||||
348 | * @return array|null|object |
||||
349 | 26 | */ |
|||
350 | public function fetchObject() |
||||
351 | { |
||||
352 | $this->Record = @mysqli_fetch_object($this->queryId); |
||||
0 ignored issues
–
show
$this->queryId of type integer is incompatible with the type mysqli_result expected by parameter $result of mysqli_fetch_object() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
353 | return $this->Record; |
||||
354 | } |
||||
355 | |||||
356 | /* public: walk result set */ |
||||
357 | 1 | ||||
358 | /** |
||||
359 | 1 | * Db::next_record() |
|||
360 | * |
||||
361 | * @param mixed $resultType |
||||
362 | 1 | * @return bool |
|||
363 | */ |
||||
364 | public function next_record($resultType = MYSQLI_BOTH) |
||||
365 | { |
||||
366 | if ($this->queryId === false) { |
||||
0 ignored issues
–
show
|
|||||
367 | $this->haltmsg('next_record called with no query pending.'); |
||||
368 | return 0; |
||||
369 | } |
||||
370 | 26 | ||||
371 | $this->Record = @mysqli_fetch_array($this->queryId, $resultType); |
||||
0 ignored issues
–
show
$this->queryId of type integer is incompatible with the type mysqli_result expected by parameter $result of mysqli_fetch_array() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
372 | 26 | ++$this->Row; |
|||
373 | $this->Errno = mysqli_errno($this->linkId); |
||||
0 ignored issues
–
show
It seems like
$this->linkId can also be of type integer ; however, parameter $mysql of mysqli_errno() does only seem to accept mysqli , 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
![]() |
|||||
374 | $this->Error = mysqli_error($this->linkId); |
||||
0 ignored issues
–
show
It seems like
$this->linkId can also be of type integer ; however, parameter $mysql of mysqli_error() does only seem to accept mysqli , 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
![]() |
|||||
375 | 26 | ||||
376 | $stat = is_array($this->Record); |
||||
377 | if (!$stat && $this->autoFree && is_resource($this->queryId)) { |
||||
0 ignored issues
–
show
|
|||||
378 | $this->free(); |
||||
379 | } |
||||
380 | return $stat; |
||||
381 | } |
||||
382 | |||||
383 | /** |
||||
384 | * switch to position in result set |
||||
385 | * |
||||
386 | * @param integer $pos the row numbe starting at 0 to switch to |
||||
387 | 2 | * @return bool whetherit was successfu or not. |
|||
388 | */ |
||||
389 | 2 | public function seek($pos = 0) |
|||
390 | { |
||||
391 | $status = @mysqli_data_seek($this->queryId, $pos); |
||||
0 ignored issues
–
show
$this->queryId of type integer is incompatible with the type mysqli_result expected by parameter $result of mysqli_data_seek() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
392 | if ($status) { |
||||
393 | 2 | $this->Row = $pos; |
|||
394 | } else { |
||||
395 | $this->haltmsg("seek({$pos}) failed: result has ".$this->num_rows().' rows', __LINE__, __FILE__); |
||||
396 | /* half assed attempt to save the day, but do not consider this documented or even desirable behaviour. */ |
||||
397 | $rows = $this->num_rows(); |
||||
398 | @mysqli_data_seek($this->queryId, $rows); |
||||
0 ignored issues
–
show
It seems like you do not handle an error condition for
mysqli_data_seek() . This can introduce security issues, and is generally not recommended.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||||
399 | $this->Row = $rows; |
||||
400 | return false; |
||||
401 | } |
||||
402 | return true; |
||||
403 | } |
||||
404 | 1 | ||||
405 | /** |
||||
406 | 1 | * Initiates a transaction |
|||
407 | 1 | * |
|||
408 | 1 | * @return bool |
|||
409 | 1 | */ |
|||
410 | 1 | public function transactionBegin() |
|||
411 | { |
||||
412 | if (version_compare(PHP_VERSION, '5.5.0') < 0) { |
||||
413 | 1 | return true; |
|||
414 | } |
||||
415 | if (!$this->connect()) { |
||||
416 | 1 | return 0; |
|||
417 | } |
||||
418 | 1 | return mysqli_begin_transaction($this->linkId); |
|||
419 | } |
||||
420 | 1 | ||||
421 | 1 | /** |
|||
422 | * Commits a transaction |
||||
423 | * |
||||
424 | * @return bool |
||||
425 | 1 | */ |
|||
426 | public function transactionCommit() |
||||
427 | { |
||||
428 | if (version_compare(PHP_VERSION, '5.5.0') < 0 || $this->linkId === 0) { |
||||
429 | return true; |
||||
430 | } |
||||
431 | return mysqli_commit($this->linkId); |
||||
0 ignored issues
–
show
It seems like
$this->linkId can also be of type integer ; however, parameter $mysql of mysqli_commit() does only seem to accept mysqli , 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
![]() |
|||||
432 | } |
||||
433 | 2 | ||||
434 | /** |
||||
435 | 2 | * Rolls back a transaction |
|||
436 | * |
||||
437 | 2 | * @return bool |
|||
438 | 2 | */ |
|||
439 | public function transactionAbort() |
||||
440 | { |
||||
441 | if (version_compare(PHP_VERSION, '5.5.0') < 0 || $this->linkId === 0) { |
||||
442 | 2 | return true; |
|||
443 | } |
||||
444 | return mysqli_rollback($this->linkId); |
||||
0 ignored issues
–
show
It seems like
$this->linkId can also be of type integer ; however, parameter $mysql of mysqli_rollback() does only seem to accept mysqli , 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
![]() |
|||||
445 | } |
||||
446 | |||||
447 | /** |
||||
448 | * This will get the last insert ID created on the current connection. Should only be called after an insert query is |
||||
449 | * run on a table that has an auto incrementing field. $table and $field are required, but unused here since it's |
||||
450 | * unnecessary for mysql. For compatibility with pgsql, the params must be supplied. |
||||
451 | 2 | * |
|||
452 | * @param string $table |
||||
453 | 2 | * @param string $field |
|||
454 | * @return int|string |
||||
455 | */ |
||||
456 | public function getLastInsertId($table, $field) |
||||
457 | { |
||||
458 | if (!isset($table) || $table == '' || !isset($field) || $field == '') { |
||||
459 | return -1; |
||||
460 | 6 | } |
|||
461 | |||||
462 | 6 | return @mysqli_insert_id($this->linkId); |
|||
0 ignored issues
–
show
It seems like
$this->linkId can also be of type integer ; however, parameter $mysql of mysqli_insert_id() does only seem to accept mysqli , 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
![]() |
|||||
463 | } |
||||
464 | |||||
465 | /* public: table locking */ |
||||
466 | |||||
467 | /** |
||||
468 | * Db::lock() |
||||
469 | 1 | * @param mixed $table |
|||
470 | * @param string $mode |
||||
471 | 1 | * @return bool|int|\mysqli_result |
|||
472 | */ |
||||
473 | public function lock($table, $mode = 'write') |
||||
474 | { |
||||
475 | $this->connect(); |
||||
476 | $query = 'lock tables '; |
||||
477 | if (is_array($table)) { |
||||
478 | foreach ($table as $key => $value) { |
||||
479 | 1 | if ($key == 'read' && $key != 0) { |
|||
480 | $query .= "$value read, "; |
||||
481 | 1 | } else { |
|||
482 | 1 | $query .= "$value $mode, "; |
|||
483 | 1 | } |
|||
484 | 1 | } |
|||
485 | 1 | $query = mb_substr($query, 0, -2); |
|||
486 | 1 | } else { |
|||
487 | 1 | $query .= "$table $mode"; |
|||
488 | 1 | } |
|||
489 | $res = @mysqli_query($this->linkId, $query); |
||||
490 | 1 | if (!$res) { |
|||
491 | $this->halt("lock($table, $mode) failed."); |
||||
492 | return 0; |
||||
493 | } |
||||
494 | return $res; |
||||
495 | } |
||||
496 | |||||
497 | /** |
||||
498 | * Db::unlock() |
||||
499 | * @param bool $haltOnError optional, defaults to TRUE, whether or not to halt on error |
||||
500 | * @return bool|int|\mysqli_result |
||||
501 | */ |
||||
502 | public function unlock($haltOnError = true) |
||||
503 | { |
||||
504 | $this->connect(); |
||||
505 | |||||
506 | $res = @mysqli_query($this->linkId, 'unlock tables'); |
||||
507 | if ($haltOnError === true && !$res) { |
||||
508 | $this->halt('unlock() failed.'); |
||||
509 | return 0; |
||||
510 | } |
||||
511 | return $res; |
||||
512 | } |
||||
513 | |||||
514 | /* public: evaluate the result (size, width) */ |
||||
515 | |||||
516 | /** |
||||
517 | * Db::affectedRows() |
||||
518 | * @return int |
||||
519 | */ |
||||
520 | public function affectedRows() |
||||
521 | { |
||||
522 | return @mysqli_affected_rows($this->linkId); |
||||
0 ignored issues
–
show
It seems like
$this->linkId can also be of type integer ; however, parameter $mysql of mysqli_affected_rows() does only seem to accept mysqli , 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
![]() |
|||||
523 | } |
||||
524 | |||||
525 | /** |
||||
526 | * Db::num_rows() |
||||
527 | * @return int |
||||
528 | */ |
||||
529 | public function num_rows() |
||||
530 | { |
||||
531 | return @mysqli_num_rows($this->queryId); |
||||
0 ignored issues
–
show
$this->queryId of type integer is incompatible with the type mysqli_result expected by parameter $result of mysqli_num_rows() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
532 | } |
||||
533 | |||||
534 | /** |
||||
535 | * Db::num_fields() |
||||
536 | * @return int |
||||
537 | */ |
||||
538 | public function num_fields() |
||||
539 | { |
||||
540 | return @mysqli_num_fields($this->queryId); |
||||
0 ignored issues
–
show
$this->queryId of type integer is incompatible with the type mysqli_result expected by parameter $result of mysqli_num_fields() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
541 | } |
||||
542 | |||||
543 | /** |
||||
544 | * gets an array of the table names in teh current datase |
||||
545 | * |
||||
546 | * @return array |
||||
547 | */ |
||||
548 | public function tableNames() |
||||
549 | { |
||||
550 | $return = []; |
||||
551 | $this->query('SHOW TABLES'); |
||||
552 | $i = 0; |
||||
553 | while ($info = $this->queryId->fetch_row()) { |
||||
0 ignored issues
–
show
The method
fetch_row() does not exist on integer .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||||
554 | $return[$i]['table_name'] = $info[0]; |
||||
555 | $return[$i]['tablespace_name'] = $this->database; |
||||
556 | $return[$i]['database'] = $this->database; |
||||
557 | ++$i; |
||||
558 | } |
||||
559 | return $return; |
||||
560 | } |
||||
561 | } |
||||
562 | |||||
563 | /** |
||||
564 | * @param $result |
||||
565 | * @param $row |
||||
566 | * @param int|string $field |
||||
567 | * @return bool |
||||
568 | */ |
||||
569 | /* |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
56% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||||
570 | function mysqli_result($result, $row, $field = 0) { |
||||
571 | if ($result === false) return false; |
||||
572 | if ($row >= mysqli_num_rows($result)) return false; |
||||
573 | if (is_string($field) && !(mb_strpos($field, '.') === false)) { |
||||
574 | $tField = explode('.', $field); |
||||
575 | $field = -1; |
||||
576 | $tFields = mysqli_fetch_fields($result); |
||||
577 | for ($id = 0, $idMax = mysqli_num_fields($result); $id < $idMax; $id++) { |
||||
578 | if ($tFields[$id]->table == $tField[0] && $tFields[$id]->name == $tField[1]) { |
||||
579 | $field = $id; |
||||
580 | break; |
||||
581 | } |
||||
582 | } |
||||
583 | if ($field == -1) return false; |
||||
584 | } |
||||
585 | mysqli_data_seek($result, $row); |
||||
586 | $line = mysqli_fetch_array($result); |
||||
587 | return isset($line[$field]) ? $line[$field] : false; |
||||
588 | } |
||||
589 | */ |
||||
590 |
In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.