Completed
Push — master ( 866be0...ac25c9 )
by Lars
11:39 queued 06:06
created

Result::get()   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 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace voku\db;
4
5
use Arrayy\Arrayy;
6
7
/**
8
 * Result: this handles the result from "DB"-Class
9
 *
10
 * @package   voku\db
11
 */
12
final class Result
13
{
14
15
  /**
16
   * @var int
17
   */
18
  public $num_rows;
19
20
  /**
21
   * @var string
22
   */
23
  public $sql;
24
25
  /**
26
   * @var \mysqli_result
27
   */
28
  private $_result;
29
30
  /**
31
   * @var string
32
   */
33
  private $_default_result_type = 'object';
34
35
  /**
36
   * @var bool
37
   */
38
  private static $_mysqlnd_is_used;
39
40
  /**
41
   * Result
42
   *
43
   * @param string         $sql
44
   * @param \mysqli_result $result
45
   */
46 24
  public function __construct($sql = '', \mysqli_result $result)
47
  {
48 24
    $this->sql = $sql;
49
50 24
    $this->_result = $result;
51 24
    $this->num_rows = $this->_result->num_rows;
52
53 24
    if (self::$_mysqlnd_is_used === null) {
54 1
      self::$_mysqlnd_is_used = extension_loaded('mysqlnd') && function_exists('mysqli_fetch_all');
55 1
    }
56 24
  }
57
58
  /**
59
   * @return string
60
   */
61 1
  public function getDefaultResultType()
62
  {
63 1
    return $this->_default_result_type;
64
  }
65
66
  /**
67
   * you can set the default result-type to 'object' or 'array'
68
   *
69
   * used for "fetch()" and "fetchAll()"
70
   *
71
   * @param string $default_result_type
72
   */
73 2
  public function setDefaultResultType($default_result_type = 'object')
74
  {
75 2
    if ($default_result_type === 'object' || $default_result_type === 'array') {
76 2
      $this->_default_result_type = $default_result_type;
77 2
    }
78 2
  }
79
80
  /**
81
   * fetch array-pair
82
   *
83
   * both "key" and "value" must exists in the fetched data
84
   * the key will be the new key of the result-array
85
   *
86
   * e.g.:
87
   *    fetchArrayPair('some_id', 'some_value');
88
   *    // array(127 => 'some value', 128 => 'some other value')
89
   *
90
   * @param string $key
91
   * @param string $value
92
   *
93
   * @return array
94
   */
95 1
  public function fetchArrayPair($key, $value)
96
  {
97 1
    $arrayPair = array();
98 1
    $data = $this->fetchAllArray();
99
100 1
    foreach ($data as $_row) {
101 1
      if (isset($_row[$key], $_row[$value])) {
102 1
        $_key = $_row[$key];
103 1
        $_value = $_row[$value];
104 1
        $arrayPair[$_key] = $_value;
105 1
      }
106 1
    }
107
108 1
    return $arrayPair;
109
  }
110
111
  /**
112
   * Cast data into int, float or string.
113
   *
114
   * INFO: install / use "mysqlnd"-driver for better performance
115
   *
116
   * @param array|object $data
117
   *
118
   * @return array|false false on error
119
   */
120 20
  private function cast(&$data)
121
  {
122 20
    if (self::$_mysqlnd_is_used === true) {
123 20
      return $data;
124
    }
125
126
    // init
127
    static $fields = array();
128
    static $types = array();
129
130
    $result_hash = spl_object_hash($this->_result);
131
132
    if (!isset($fields[$result_hash])) {
133
      $fields[$result_hash] = mysqli_fetch_fields($this->_result);
134
    }
135
136
    if ($fields[$result_hash] === false) {
137
      return false;
138
    }
139
140
    if (!isset($types[$result_hash])) {
141
      foreach ($fields[$result_hash] as $field) {
142
        switch ($field->type) {
143
          case 3:
144
            $types[$result_hash][$field->name] = 'int';
145
            break;
146
          case 4:
147
            $types[$result_hash][$field->name] = 'float';
148
            break;
149
          default:
150
            $types[$result_hash][$field->name] = 'string';
151
            break;
152
        }
153
      }
154
    }
155
156
    if (is_array($data) === true) {
157 View Code Duplication
      foreach ($types[$result_hash] as $type_name => $type) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
158
        if (isset($data[$type_name])) {
159
          settype($data[$type_name], $type);
160
        }
161
      }
162
    } elseif (is_object($data)) {
163 View Code Duplication
      foreach ($types[$result_hash] as $type_name => $type) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
164
        if (isset($data->{$type_name})) {
165
          settype($data->{$type_name}, $type);
166
        }
167
      }
168
    }
169
170
    return $data;
171
  }
172
173
  /**
174
   * fetchAllArray
175
   *
176
   * @return array
177
   */
178 11 View Code Duplication
  public function fetchAllArray()
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...
179
  {
180
    // init
181 11
    $data = array();
182
183
    if (
184 11
        $this->_result
185 11
        &&
186 11
        !$this->is_empty()
187 11
    ) {
188 11
      $this->reset();
189
190
      /** @noinspection PhpAssignmentInConditionInspection */
191 11
      while ($row = mysqli_fetch_assoc($this->_result)) {
192 11
        $data[] = $this->cast($row);
193 11
      }
194 11
    }
195
196 11
    return $data;
197
  }
198
199
  /**
200
   * fetch all results, return via Arrayy
201
   *
202
   * @return Arrayy
203
   */
204 1 View Code Duplication
  public function fetchAllArrayy()
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...
205
  {
206
    // init
207 1
    $data = array();
208
209
    if (
210 1
        $this->_result
211 1
        &&
212 1
        !$this->is_empty()
213 1
    ) {
214 1
      $this->reset();
215
216
      /** @noinspection PhpAssignmentInConditionInspection */
217 1
      while ($row = mysqli_fetch_assoc($this->_result)) {
218 1
        $data[] = $this->cast($row);
219 1
      }
220 1
    }
221
222 1
    return Arrayy::create($data);
223
  }
224
225
  /**
226
   * is_empty
227
   *
228
   * @return bool
229
   */
230 13
  public function is_empty()
231
  {
232 13
    if ($this->num_rows > 0) {
233 13
      return false;
234
    } else {
235 1
      return true;
236
    }
237
  }
238
239
  /**
240
   * reset
241
   *
242
   * @return Result
243
   */
244 12
  public function reset()
245
  {
246 12
    if (!$this->is_empty()) {
247 12
      mysqli_data_seek($this->_result, 0);
248 12
    }
249
250 12
    return $this;
251
  }
252
253
  /**
254
   * json
255
   *
256
   * @return string
257
   */
258 1
  public function json()
259
  {
260 1
    $data = $this->fetchAllArray();
261
262 1
    return json_encode($data);
263
  }
264
265
  /**
266
   * __destruct
267
   *
268
   */
269 24
  public function __destruct()
270
  {
271 24
    $this->free();
272 24
  }
273
274
  /**
275
   * free
276
   */
277 24
  public function free()
278
  {
279 24
    mysqli_free_result($this->_result);
280 24
  }
281
282
  /**
283
   * get
284
   *
285
   * @return array|object|false false on error
286
   */
287 1
  public function get()
288
  {
289 1
    return $this->fetch();
290
  }
291
292
  /**
293
   * fetch (object -> not a array by default)
294
   *
295
   * @param $reset
296
   *
297
   * @return array|object|false false on error
298
   */
299 2
  public function fetch($reset = false)
300
  {
301 2
    $return = false;
302
303 2
    if ($this->_default_result_type === 'object') {
304 2
      $return = $this->fetchObject('', '', $reset);
305 2
    } elseif ($this->_default_result_type === 'array') {
306 2
      $return = $this->fetchArray($reset);
307 2
    }
308
309 2
    return $return;
310
  }
311
312
  /**
313
   * fetchObject
314
   *
315
   * @param string     $class
316
   * @param null|array $params
317
   * @param bool       $reset
318
   *
319
   * @return object|false false on error
320
   */
321 5
  public function fetchObject($class = '', $params = null, $reset = false)
322
  {
323 5
    if ($reset === true) {
324 1
      $this->reset();
325 1
    }
326
327 5
    if ($class && $params) {
328 1
      return ($row = mysqli_fetch_object($this->_result, $class, $params)) ? $row : false;
329
    }
330
331 5
    if ($class) {
332 1
      return ($row = mysqli_fetch_object($this->_result, $class)) ? $row : false;
333
    }
334
335 5
    return ($row = mysqli_fetch_object($this->_result)) ? $this->cast($row) : false;
336
  }
337
338
  /**
339
   * fetch as array
340
   *
341
   * @param bool $reset
342
   *
343
   * @return array|false false on error
344
   */
345 9 View Code Duplication
  public function fetchArray($reset = false)
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...
346
  {
347 9
    if ($reset === true) {
348 1
      $this->reset();
349 1
    }
350
351 9
    $row = mysqli_fetch_assoc($this->_result);
352 9
    if ($row) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $row 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...
353 9
      return $this->cast($row);
354
    }
355
356
    return false;
357
  }
358
359
  /**
360
   * fetch as Arrayy-Object
361
   *
362
   * @param bool $reset
363
   *
364
   * @return Arrayy|false false on error
365
   */
366 1 View Code Duplication
  public function fetchArrayy($reset = false)
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...
367
  {
368 1
    if ($reset === true) {
369
      $this->reset();
370
    }
371
372 1
    $row = mysqli_fetch_assoc($this->_result);
373 1
    if ($row) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $row 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...
374 1
      return Arrayy::create($this->cast($row));
0 ignored issues
show
Bug introduced by
It seems like $this->cast($row) targeting voku\db\Result::cast() can also be of type false or object; however, Arrayy\Arrayy::create() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
375
    }
376
377
    return false;
378
  }
379
380
  /**
381
   * getAll
382
   *
383
   * @return array
384
   */
385 1
  public function getAll()
386
  {
387 1
    return $this->fetchAll();
388
  }
389
390
  /**
391
   * fetchAll
392
   *
393
   * @return array
394
   */
395 2
  public function fetchAll()
396
  {
397 2
    $return = array();
398
399 2
    if ($this->_default_result_type === 'object') {
400 2
      $return = $this->fetchAllObject();
401 2
    } elseif ($this->_default_result_type === 'array') {
402 1
      $return = $this->fetchAllArray();
403 1
    }
404
405 2
    return $return;
406
  }
407
408
  /**
409
   * fetchAllObject
410
   *
411
   * @param string     $class
412
   * @param null|array $params
413
   *
414
   * @return array
415
   */
416 3
  public function fetchAllObject($class = '', $params = null)
417
  {
418
    // init
419 3
    $data = array();
420
421 3
    if (!$this->is_empty()) {
422 3
      $this->reset();
423
424 3
      if ($class && $params) {
425
        /** @noinspection PhpAssignmentInConditionInspection */
426 1
        while ($row = mysqli_fetch_object($this->_result, $class, $params)) {
427 1
          $data[] = $row;
428 1
        }
429 3
      } elseif ($class) {
430
        /** @noinspection PhpAssignmentInConditionInspection */
431 1
        while ($row = mysqli_fetch_object($this->_result, $class)) {
432 1
          $data[] = $row;
433 1
        }
434 1
      } else {
435
        /** @noinspection PhpAssignmentInConditionInspection */
436 3
        while ($row = mysqli_fetch_object($this->_result)) {
437 3
          $data[] = $this->cast($row);
438 3
        }
439
      }
440 3
    }
441
442 3
    return $data;
443
  }
444
445
  /**
446
   * getObject
447
   *
448
   * @return array of mysql-objects
449
   */
450 1
  public function getObject()
451
  {
452 1
    return $this->fetchAllObject();
453
  }
454
455
  /**
456
   * getArray
457
   *
458
   * @return array
459
   */
460 1
  public function getArray()
461
  {
462 1
    return $this->fetchAllArray();
463
  }
464
465
  /**
466
   * getColumn
467
   *
468
   * @param $key
469
   *
470
   * @return string
471
   */
472 1
  public function getColumn($key)
473
  {
474 1
    return $this->fetchColumn($key);
475
  }
476
477
  /**
478
   * fetchColumn
479
   *
480
   * @param string $column
481
   *
482
   * @return string empty string if the $column wasn't found
483
   */
484 2
  public function fetchColumn($column = '')
485
  {
486 2
    $columnData = '';
487 2
    $data = $this->fetchAllArray();
488
489 2
    foreach ($data as $_row) {
490 2
      if (isset($_row[$column])) {
491 2
        $columnData = $_row[$column];
492 2
      }
493 2
    }
494
495 2
    return $columnData;
496
  }
497
498
  /**
499
   * get the num-rows as string
500
   *
501
   * @return string
502
   */
503 1
  public function __toString()
504
  {
505 1
    return (string)$this->num_rows;
506
  }
507
}
508