Completed
Pull Request — master (#23)
by Lars
14:40 queued 01:07
created

Prepare::get_sql_with_bound_parameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace voku\db;
4
5
use voku\db\exceptions\DBGoneAwayException;
6
use voku\db\exceptions\QueryException;
7
use voku\helper\Bootup;
8
9
/**
10
 * Prepare: this handles the prepare-statement from "DB"-Class
11
 *
12
 * @package   voku\db
13
 */
14
final class Prepare extends \mysqli_stmt
15
{
16
17
  /**
18
   * @var string $_sql - the unchanged query string provided to the constructor
19
   */
20
  private $_sql;
21
22
  /**
23
   * @var string $_sql_with_bound_parameters - the query string with bound parameters interpolated
24
   */
25
  private $_sql_with_bound_parameters;
26
27
  /**
28
   * @var bool
29
   */
30
  private $_use_bound_parameters_interpolated = false;
31
32
  /**
33
   * @var array $_boundParams - array of arrays containing values that have been bound to the query as parameters
34
   */
35
  private $_boundParams = array();
36
37
  /**
38
   * @var DB
39
   */
40
  private $_db;
41
42
  /**
43
   * @var Debug
44
   */
45
  private $_debug;
46
47
  /**
48
   * Prepare constructor.
49
   *
50
   * @param DB     $db
51
   * @param string $query
52
   */
53 9
  public function __construct(DB $db, $query)
54
  {
55 9
    $this->_db = $db;
56 9
    $this->_debug = $db->getDebugger();
57
58 9
    parent::__construct($db->getLink(), $query);
59
60 9
    $this->prepare($query);
61 9
  }
62
63
  /**
64
   * Prepare destructor.
65
   */
66 9
  public function __destruct()
67
  {
68 9
    $this->close();
69 9
  }
70
71
  /**
72
   * Combines the values stored in $this->boundParams into one array suitable for pushing as the input arguments to
73
   * parent::bind_param when used with call_user_func_array
74
   *
75
   * @return array
76
   */
77 6
  private function _buildArguments()
78
  {
79 6
    $arguments = array();
80 6
    $arguments[0] = '';
81
82 6
    foreach ($this->_boundParams as $param) {
83 6
      $arguments[0] .= $param['type'];
84 6
      $arguments[] =& $param['value'];
85 6
    }
86
87 6
    return $arguments;
88
  }
89
90
  /**
91
   * Escapes the supplied value.
92
   *
93
   * @param array $param
94
   *
95
   * @return array 0 => "$value" escaped<br />
96
   *               1 => "$valueForSqlWithBoundParameters" for insertion into the interpolated query string
97
   */
98 6
  private function _prepareValue(&$param)
99
  {
100 6
    $type = $param['type']; // 'i', 'b', 's', 'd'
101 6
    $value = $param['value'];
102
103
    /** @noinspection ReferenceMismatchInspection */
104 6
    $value = $this->_db->escape($value);
105
106 6
    if ($type === 's') {
107 4
      $valueForSqlWithBoundParameters = "'" . $value . "'";
108 6
    } elseif ($type === 'i') {
109 2
      $valueForSqlWithBoundParameters = (int)$value;
110 2
    } elseif ($type === 'd') {
111 1
      $valueForSqlWithBoundParameters = (double)$value;
112 1
    } else {
113
      $valueForSqlWithBoundParameters = $value;
114
    }
115
116 6
    return array($value, $valueForSqlWithBoundParameters);
117
  }
118
119
  /**
120
   * @return int
121
   */
122
  public function affected_rows()
123
  {
124
    return $this->affected_rows;
125
  }
126
127
  /**
128
   * This is a wrapper for "bind_param" what binds variables to a prepared statement as parameters. If you use this
129
   * wrapper, you can debug your query with e.g. "$this->get_sql_with_bound_parameters()".
130
   *
131
   * @param string $types <strong>i<strong> corresponding variable has type integer<br />
132
   *                      <strong>d</strong> corresponding variable has type double<br />
133
   *                      <strong>s</strong> corresponding variable has type string<br />
134
   *                      <strong>b</strong> corresponding variable is a blob and will be sent in packets
135
   *
136
   * INFO: We have to explicitly declare all parameters as references, otherwise it does not seem possible to pass them
137
   * on without losing the reference property.
138
   *
139
   * @param mixed  $v1
140
   * @param mixed  $v2
141
   * @param mixed  $v3
142
   * @param mixed  $v4
143
   * @param mixed  $v5
144
   * @param mixed  $v6
145
   * @param mixed  $v7
146
   * @param mixed  $v8
147
   * @param mixed  $v9
148
   * @param mixed  $v10
149
   * @param mixed  $v11
150
   * @param mixed  $v12
151
   * @param mixed  $v13
152
   * @param mixed  $v14
153
   * @param mixed  $v15
154
   * @param mixed  $v16
155
   * @param mixed  $v17
156
   * @param mixed  $v18
157
   * @param mixed  $v19
158
   * @param mixed  $v20
159
   * @param mixed  $v21
160
   * @param mixed  $v22
161
   * @param mixed  $v23
162
   * @param mixed  $v24
163
   * @param mixed  $v25
164
   * @param mixed  $v26
165
   * @param mixed  $v27
166
   * @param mixed  $v28
167
   * @param mixed  $v29
168
   * @param mixed  $v30
169
   * @param mixed  $v31
170
   * @param mixed  $v32
171
   * @param mixed  $v33
172
   * @param mixed  $v34
173
   * @param mixed  $v35
174
   *
175
   * @return mixed
176
   */
177 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)
0 ignored issues
show
Unused Code introduced by
The parameter $v1 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v2 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v3 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v4 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v5 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v6 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v7 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v8 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v9 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v10 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v11 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v12 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v13 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v14 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v15 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v16 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v17 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v18 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v19 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v20 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v21 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v22 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v23 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v24 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v25 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v26 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v27 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v28 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v29 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v30 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v31 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v32 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v33 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v34 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $v35 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
178
  {
179 6
    $this->_use_bound_parameters_interpolated = true;
180
181
    // debug_backtrace returns arguments by reference, see comments at http://php.net/manual/de/function.func-get-args.php
182 6
    if (Bootup::is_php('5.4')) {
183 6
      $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 1);
184 6
    } else {
185
      $trace = debug_backtrace();
186
    }
187
188 6
    $args =& $trace[0]['args'];
189 6
    $types = str_split($types);
190
191 6
    $args_count = count($args) - 1;
192 6
    $types_count = count($types);
193
194 6
    if ($args_count !== $types_count) {
195
      trigger_error('Number of variables doesn\'t match number of parameters in prepared statement', E_WARNING);
196
197
      return false;
198
    }
199
200 6
    $arg = 1;
201 6
    foreach ($types as $typeInner) {
202 6
      $val =& $args[$arg];
203 6
      $this->_boundParams[] = array(
204 6
          'type'  => $typeInner,
205 6
          'value' => &$val,
206
      );
207 6
      $arg++;
208 6
    }
209
210 6
    return true;
211
  }
212
213
  /**
214
   * @inheritdoc
215
   *
216
   * @return bool
217
   */
218
  public function execute_raw()
219
  {
220
    return parent::execute();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (execute() instead of execute_raw()). Are you sure this is correct? If so, you might want to change this to $this->execute().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
221
  }
222
223
  /**
224
   * Executes a prepared Query
225
   *
226
   * @link http://php.net/manual/en/mysqli-stmt.execute.php
227
   *
228
   * @return bool|int|Result   "Result" by "<b>SELECT</b>"-queries<br />
229
   *                           "int" (insert_id) by "<b>INSERT / REPLACE</b>"-queries<br />
230
   *                           "int" (affected_rows) by "<b>UPDATE / DELETE</b>"-queries<br />
231
   *                           "true" by e.g. "DROP"-queries<br />
232
   *                           "false" on error
233
   */
234 9
  public function execute()
235
  {
236 9
    if ($this->_use_bound_parameters_interpolated === true) {
237 6
      $this->interpolateQuery();
238 6
      call_user_func_array(array('parent', 'bind_param'), $this->_buildArguments());
239 6
    }
240
241 9
    $query_start_time = microtime(true);
242 9
    $result = parent::execute();
243 9
    $query_duration = microtime(true) - $query_start_time;
244
245 9
    if ($result === true) {
246
247
      // "INSERT" || "REPLACE"
248 7 View Code Duplication
      if (preg_match('/^\s*"?(INSERT|REPLACE)\s+/i', $this->_sql)) {
249 3
        $insert_id = (int)$this->insert_id;
250 3
        $this->_debug->logQuery($this->_sql_with_bound_parameters, $query_duration, $insert_id);
251
252 3
        return $insert_id;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $insert_id; (integer) is incompatible with the return type of the parent method mysqli_stmt::execute of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
253
      }
254
255
      // "UPDATE" || "DELETE"
256 4 View Code Duplication
      if (preg_match('/^\s*"?(UPDATE|DELETE)\s+/i', $this->_sql)) {
257 2
        $affected_rows = (int)$this->affected_rows;
258 2
        $this->_debug->logQuery($this->_sql_with_bound_parameters, $query_duration, $affected_rows);
259
260 2
        return $affected_rows;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $affected_rows; (integer) is incompatible with the return type of the parent method mysqli_stmt::execute of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
261
      }
262
263
      // "SELECT"
264 2
      if (preg_match('/^\s*"?(SELECT)\s+/i', $this->_sql)) {
265 2
        $result = $this->get_result();
0 ignored issues
show
Bug introduced by
The method get_result() does not seem to exist on object<voku\db\Prepare>.

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.

Loading history...
266 2
        $num_rows = (int)$result->num_rows;
267 2
        $this->_debug->logQuery($this->_sql_with_bound_parameters, $query_duration, $num_rows);
268
269 2
        return new Result($this->_sql_with_bound_parameters, $result);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \voku\db\Resu...d_parameters, $result); (voku\db\Result) is incompatible with the return type of the parent method mysqli_stmt::execute of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
270
      }
271
272
      // log the ? query
273
      $this->_debug->logQuery($this->_sql_with_bound_parameters, $query_duration, 0);
274
275
      return true;
276
    }
277
278
    // log the error query
279 2
    $this->_debug->logQuery($this->_sql_with_bound_parameters, $query_duration, 0, true);
280
281 2
    return $this->queryErrorHandling($this->error, $this->_sql_with_bound_parameters);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->queryError...with_bound_parameters); (boolean|integer|voku\db\Result) is incompatible with the return type of the parent method mysqli_stmt::execute of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
282
  }
283
284
  /**
285
   * Prepare an SQL statement for execution
286
   *
287
   * @link  http://php.net/manual/en/mysqli-stmt.prepare.php
288
   *
289
   * @param string $query <p>
290
   *                      The query, as a string. It must consist of a single SQL statement.
291
   *                      </p>
292
   *                      <p>
293
   *                      You can include one or more parameter markers in the SQL statement by
294
   *                      embedding question mark (?) characters at the
295
   *                      appropriate positions.
296
   *                      </p>
297
   *                      <p>
298
   *                      You should not add a terminating semicolon or \g
299
   *                      to the statement.
300
   *                      </p>
301
   *                      <p>
302
   *                      The markers are legal only in certain places in SQL statements.
303
   *                      For example, they are allowed in the VALUES() list of an INSERT statement
304
   *                      (to specify column values for a row), or in a comparison with a column in
305
   *                      a WHERE clause to specify a comparison value.
306
   *                      </p>
307
   *                      <p>
308
   *                      However, they are not allowed for identifiers (such as table or column names),
309
   *                      in the select list that names the columns to be returned by a SELECT statement),
310
   *                      or to specify both operands of a binary operator such as the =
311
   *                      equal sign. The latter restriction is necessary because it would be impossible
312
   *                      to determine the parameter type. In general, parameters are legal only in Data
313
   *                      Manipulation Language (DML) statements, and not in Data Definition Language
314
   *                      (DDL) statements.
315
   *                      </p>
316
   *
317
   * @return bool false on error
318
   * @since 5.0
319
   */
320 9
  public function prepare($query)
321
  {
322 9
    $this->_sql = $query;
323 9
    $this->_sql_with_bound_parameters = $query;
324
325 9
    if (!$this->_db->isReady()) {
326
      return false;
327
    }
328
329 9 View Code Duplication
    if (!$query || $query === '') {
330
      $this->_debug->displayError('Can not prepare an empty query.', false);
331
332
      return false;
333
    }
334
335 9
    $bool = parent::prepare($query);
336
337 9
    if ($bool === false) {
338 2
      $this->_debug->displayError('Can not prepare query: ' . $query . ' | ' . $this->error, false);
339 2
    }
340
341 9
    return $bool;
342
  }
343
344
  /**
345
   * Ger the bound parameters from sql-query as array, if you use the "$this->bind_param_debug()" method.
346
   *
347
   * @return array
348
   */
349
  public function get_bound_params()
350
  {
351
    return $this->_boundParams;
352
  }
353
354
  /**
355
   * @return string
356
   */
357
  public function get_sql()
358
  {
359
    return $this->_sql;
360
  }
361
362
  /**
363
   * Get the sql-query with bound parameters, if you use the "$this->bind_param_debug()" method.
364
   *
365
   * @return string
366
   */
367 4
  public function get_sql_with_bound_parameters()
368
  {
369 4
    return $this->_sql_with_bound_parameters;
370
  }
371
372
  /**
373
   * @return int
374
   */
375
  public function insert_id()
376
  {
377
    return $this->insert_id;
378
  }
379
380
  /**
381
   * Copies $this->_sql then replaces bound markers with associated values ($this->_sql is not modified
382
   * but the resulting query string is assigned to $this->sql_bound_parameters)
383
   *
384
   * @return string $testQuery - interpolated db query string
385
   */
386 6
  private function interpolateQuery()
387
  {
388 6
    $testQuery = $this->_sql;
389 6
    if ($this->_boundParams) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_boundParams of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
390 6
      foreach ($this->_boundParams as &$param) {
391 6
        $values = $this->_prepareValue($param);
392
393
        // set new values
394 6
        $param['value'] = $values[0];
395
        // we need to replace the question mark "?" here
396 6
        $values[1] = str_replace('?', '###simple_mysqli__prepare_question_mark###', $values[1]);
397
        // build the query (only for debugging)
398 6
        $testQuery = preg_replace("/\?/", $values[1], $testQuery, 1);
399 6
      }
400 6
      unset($param);
401 6
      $testQuery = str_replace('###simple_mysqli__prepare_question_mark###', '?', $testQuery);
402 6
    }
403 6
    $this->_sql_with_bound_parameters = $testQuery;
404
405 6
    return $testQuery;
406
  }
407
408
  /**
409
   * Error-handling for the sql-query.
410
   *
411
   * @param string $errorMsg
412
   * @param string $sql
413
   *
414
   * @throws QueryException
415
   * @throws DBGoneAwayException
416
   *
417
   * @return bool
418
   */
419 2 View Code Duplication
  private function queryErrorHandling($errorMsg, $sql)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
420
  {
421 2
    if ($errorMsg === 'DB server has gone away' || $errorMsg === 'MySQL server has gone away') {
422
      static $RECONNECT_COUNTER;
423
424
      // exit if we have more then 3 "DB server has gone away"-errors
425
      if ($RECONNECT_COUNTER > 3) {
426
        $this->_debug->mailToAdmin('DB-Fatal-Error', $errorMsg . ":\n<br />" . $sql, 5);
427
        throw new DBGoneAwayException($errorMsg);
428
      }
429
430
      $this->_debug->mailToAdmin('DB-Error', $errorMsg . ":\n<br />" . $sql);
431
432
      // reconnect
433
      $RECONNECT_COUNTER++;
434
      $this->_db->reconnect(true);
435
436
      // re-run the current query
437
      return $this->execute();
438
    }
439
440 2
    $this->_debug->mailToAdmin('SQL-Error', $errorMsg . ":\n<br />" . $sql);
441
442
    // this query returned an error, we must display it (only for dev) !!!
443 2
    $this->_debug->displayError($errorMsg . ' | ' . $sql);
444
445 2
    return false;
446
  }
447
448
}
449