Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 12 | final class Prepare extends \mysqli_stmt |
||
| 13 | { |
||
| 14 | |||
| 15 | /** |
||
| 16 | * @var string $_sql - the unchanged query string provided to the constructor |
||
| 17 | */ |
||
| 18 | private $_sql; |
||
| 19 | |||
| 20 | /** |
||
| 21 | * @var string $_sql_with_bound_parameters - the query string with bound parameters interpolated |
||
| 22 | */ |
||
| 23 | private $_sql_with_bound_parameters; |
||
| 24 | |||
| 25 | /** |
||
| 26 | * @var bool |
||
| 27 | */ |
||
| 28 | private $_use_bound_parameters_interpolated = false; |
||
| 29 | |||
| 30 | /** |
||
| 31 | * @var array $_boundParams - array of arrays containing values that have been bound to the query as parameters |
||
| 32 | */ |
||
| 33 | private $_boundParams = array(); |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @var DB |
||
| 37 | */ |
||
| 38 | private $_db; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @var Debug |
||
| 42 | */ |
||
| 43 | private $_debug; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * Prepare constructor. |
||
| 47 | * |
||
| 48 | * @param DB $db |
||
| 49 | * @param string $query |
||
| 50 | */ |
||
| 51 | 9 | public function __construct(DB $db, $query) |
|
| 60 | |||
| 61 | /** |
||
| 62 | * Prepare destructor. |
||
| 63 | */ |
||
| 64 | 9 | public function __destruct() |
|
| 68 | |||
| 69 | /** |
||
| 70 | * Combines the values stored in $this->boundParams into one array suitable for pushing as the input arguments to |
||
| 71 | * parent::bind_param when used with call_user_func_array |
||
| 72 | * |
||
| 73 | * @return array |
||
| 74 | */ |
||
| 75 | 6 | private function _buildArguments() |
|
| 87 | |||
| 88 | /** |
||
| 89 | * Escapes the supplied value. |
||
| 90 | * |
||
| 91 | * @param array $param |
||
| 92 | * |
||
| 93 | * @return array 0 => "$value" escaped<br /> |
||
| 94 | * 1 => "$valueForSqlWithBoundParameters" for insertion into the interpolated query string |
||
| 95 | */ |
||
| 96 | 6 | private function _prepareValue(&$param) |
|
| 97 | { |
||
| 98 | 6 | $type = $param['type']; // 'i', 'b', 's', 'd' |
|
|
|
|||
| 99 | 6 | $value = $param['value']; |
|
| 100 | |||
| 101 | /** @noinspection ReferenceMismatchInspection */ |
||
| 102 | 6 | $value = $this->_db->escape($value); |
|
| 103 | |||
| 104 | 6 | if ($type === 's') { |
|
| 105 | 4 | $valueForSqlWithBoundParameters = "'" . $value . "'"; |
|
| 106 | 6 | } elseif ($type === 'i') { |
|
| 107 | 2 | $valueForSqlWithBoundParameters = (int)$value; |
|
| 108 | 2 | } elseif ($type === 'd') { |
|
| 109 | 1 | $valueForSqlWithBoundParameters = (double)$value; |
|
| 110 | 1 | } else { |
|
| 111 | $valueForSqlWithBoundParameters = $value; |
||
| 112 | } |
||
| 113 | |||
| 114 | 6 | return array($value, $valueForSqlWithBoundParameters); |
|
| 115 | } |
||
| 116 | |||
| 117 | /** |
||
| 118 | * @return int |
||
| 119 | */ |
||
| 120 | public function affected_rows() |
||
| 124 | |||
| 125 | /** |
||
| 126 | * This is a wrapper for "bind_param" what binds variables to a prepared statement as parameters. If you use this |
||
| 127 | * wrapper, you can debug your query with e.g. "$this->get_sql_with_bound_parameters()". |
||
| 128 | * |
||
| 129 | * @param string $types <strong>i<strong> corresponding variable has type integer<br /> |
||
| 130 | * <strong>d</strong> corresponding variable has type double<br /> |
||
| 131 | * <strong>s</strong> corresponding variable has type string<br /> |
||
| 132 | * <strong>b</strong> corresponding variable is a blob and will be sent in packets |
||
| 133 | * |
||
| 134 | * INFO: We have to explicitly declare all parameters as references, otherwise it does not seem possible to pass them |
||
| 135 | * on without losing the reference property. |
||
| 136 | * |
||
| 137 | * @param mixed $v1 |
||
| 138 | * @param mixed $v2 |
||
| 139 | * @param mixed $v3 |
||
| 140 | * @param mixed $v4 |
||
| 141 | * @param mixed $v5 |
||
| 142 | * @param mixed $v6 |
||
| 143 | * @param mixed $v7 |
||
| 144 | * @param mixed $v8 |
||
| 145 | * @param mixed $v9 |
||
| 146 | * @param mixed $v10 |
||
| 147 | * @param mixed $v11 |
||
| 148 | * @param mixed $v12 |
||
| 149 | * @param mixed $v13 |
||
| 150 | * @param mixed $v14 |
||
| 151 | * @param mixed $v15 |
||
| 152 | * @param mixed $v16 |
||
| 153 | * @param mixed $v17 |
||
| 154 | * @param mixed $v18 |
||
| 155 | * @param mixed $v19 |
||
| 156 | * @param mixed $v20 |
||
| 157 | * @param mixed $v21 |
||
| 158 | * @param mixed $v22 |
||
| 159 | * @param mixed $v23 |
||
| 160 | * @param mixed $v24 |
||
| 161 | * @param mixed $v25 |
||
| 162 | * @param mixed $v26 |
||
| 163 | * @param mixed $v27 |
||
| 164 | * @param mixed $v28 |
||
| 165 | * @param mixed $v29 |
||
| 166 | * @param mixed $v30 |
||
| 167 | * @param mixed $v31 |
||
| 168 | * @param mixed $v32 |
||
| 169 | * @param mixed $v33 |
||
| 170 | * @param mixed $v34 |
||
| 171 | * @param mixed $v35 |
||
| 172 | * |
||
| 173 | * @return mixed |
||
| 174 | */ |
||
| 175 | 6 | public function bind_param_debug($types, &$v1 = null, &$v2 = null, &$v3 = null, &$v4 = null, &$v5 = null, &$v6 = null, &$v7 = null, &$v8 = null, &$v9 = null, &$v10 = null, &$v11 = null, &$v12 = null, &$v13 = null, &$v14 = null, &$v15 = null, &$v16 = null, &$v17 = null, &$v18 = null, &$v19 = null, &$v20 = null, &$v21 = null, &$v22 = null, &$v23 = null, &$v24 = null, &$v25 = null, &$v26 = null, &$v27 = null, &$v28 = null, &$v29 = null, &$v30 = null, &$v31 = null, &$v32 = null, &$v33 = null, &$v34 = null, &$v35 = null) |
|
| 210 | |||
| 211 | /** |
||
| 212 | * @inheritdoc |
||
| 213 | * |
||
| 214 | * @return bool |
||
| 215 | */ |
||
| 216 | public function execute_raw() |
||
| 217 | { |
||
| 218 | return parent::execute(); |
||
| 219 | } |
||
| 220 | |||
| 221 | /** |
||
| 222 | * Executes a prepared Query |
||
| 223 | * |
||
| 224 | * @link http://php.net/manual/en/mysqli-stmt.execute.php |
||
| 225 | * |
||
| 226 | * @return bool|int|Result "Result" by "<b>SELECT</b>"-queries<br /> |
||
| 227 | * "int" (insert_id) by "<b>INSERT / REPLACE</b>"-queries<br /> |
||
| 228 | * "int" (affected_rows) by "<b>UPDATE / DELETE</b>"-queries<br /> |
||
| 229 | * "true" by e.g. "DROP"-queries<br /> |
||
| 230 | * "false" on error |
||
| 231 | */ |
||
| 232 | 9 | public function execute() |
|
| 281 | |||
| 282 | /** |
||
| 283 | * Prepare an SQL statement for execution |
||
| 284 | * |
||
| 285 | * @link http://php.net/manual/en/mysqli-stmt.prepare.php |
||
| 286 | * |
||
| 287 | * @param string $query <p> |
||
| 288 | * The query, as a string. It must consist of a single SQL statement. |
||
| 289 | * </p> |
||
| 290 | * <p> |
||
| 291 | * You can include one or more parameter markers in the SQL statement by |
||
| 292 | * embedding question mark (?) characters at the |
||
| 293 | * appropriate positions. |
||
| 294 | * </p> |
||
| 295 | * <p> |
||
| 296 | * You should not add a terminating semicolon or \g |
||
| 297 | * to the statement. |
||
| 298 | * </p> |
||
| 299 | * <p> |
||
| 300 | * The markers are legal only in certain places in SQL statements. |
||
| 301 | * For example, they are allowed in the VALUES() list of an INSERT statement |
||
| 302 | * (to specify column values for a row), or in a comparison with a column in |
||
| 303 | * a WHERE clause to specify a comparison value. |
||
| 304 | * </p> |
||
| 305 | * <p> |
||
| 306 | * However, they are not allowed for identifiers (such as table or column names), |
||
| 307 | * in the select list that names the columns to be returned by a SELECT statement), |
||
| 308 | * or to specify both operands of a binary operator such as the = |
||
| 309 | * equal sign. The latter restriction is necessary because it would be impossible |
||
| 310 | * to determine the parameter type. In general, parameters are legal only in Data |
||
| 311 | * Manipulation Language (DML) statements, and not in Data Definition Language |
||
| 312 | * (DDL) statements. |
||
| 313 | * </p> |
||
| 314 | * |
||
| 315 | * @return bool false on error |
||
| 316 | * @since 5.0 |
||
| 317 | */ |
||
| 318 | 9 | public function prepare($query) |
|
| 341 | |||
| 342 | /** |
||
| 343 | * Ger the bound parameters from sql-query as array, if you use the "$this->bind_param_debug()" method. |
||
| 344 | * |
||
| 345 | * @return array |
||
| 346 | */ |
||
| 347 | public function get_bound_params() |
||
| 351 | |||
| 352 | /** |
||
| 353 | * @return string |
||
| 354 | */ |
||
| 355 | public function get_sql() |
||
| 359 | |||
| 360 | /** |
||
| 361 | * Get the sql-query with bound parameters, if you use the "$this->bind_param_debug()" method. |
||
| 362 | * |
||
| 363 | * @return string |
||
| 364 | */ |
||
| 365 | 4 | public function get_sql_with_bound_parameters() |
|
| 369 | |||
| 370 | /** |
||
| 371 | * @return int |
||
| 372 | */ |
||
| 373 | public function insert_id() |
||
| 377 | |||
| 378 | /** |
||
| 379 | * Copies $this->_sql then replaces bound markers with associated values ($this->_sql is not modified |
||
| 380 | * but the resulting query string is assigned to $this->sql_bound_parameters) |
||
| 381 | * |
||
| 382 | * @return string $testQuery - interpolated db query string |
||
| 383 | */ |
||
| 384 | 6 | private function interpolateQuery() |
|
| 405 | |||
| 406 | /** |
||
| 407 | * Error-handling for the sql-query. |
||
| 408 | * |
||
| 409 | * @param string $errorMsg |
||
| 410 | * @param string $sql |
||
| 411 | * |
||
| 412 | * @throws \Exception |
||
| 413 | * |
||
| 414 | * @return bool |
||
| 415 | */ |
||
| 416 | 2 | View Code Duplication | private function queryErrorHandling($errorMsg, $sql) |
| 444 | |||
| 445 | } |
||
| 446 |
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.