Completed
Push — master ( 1be798...5156a7 )
by Lars
03:46
created

Result::getArray()   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
c 0
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
   * Result
37
   *
38
   * @param string         $sql
39
   * @param \mysqli_result $result
40
   */
41 24
  public function __construct($sql = '', \mysqli_result $result)
42
  {
43 24
    $this->sql = $sql;
44
45 24
    $this->_result = $result;
46 24
    $this->num_rows = $this->_result->num_rows;
47 24
  }
48
49
  /**
50
   * @return string
51
   */
52 1
  public function getDefaultResultType()
53
  {
54 1
    return $this->_default_result_type;
55
  }
56
57
  /**
58
   * you can set the default result-type to 'object' or 'array'
59
   *
60
   * used for "fetch()" and "fetchAll()"
61
   *
62
   * @param string $default_result_type
63
   */
64 2
  public function setDefaultResultType($default_result_type = 'object')
65
  {
66 2
    if ($default_result_type === 'object' || $default_result_type === 'array') {
67 2
      $this->_default_result_type = $default_result_type;
68 2
    }
69 2
  }
70
71
  /**
72
   * fetch array-pair
73
   *
74
   * both "key" and "value" must exists in the fetched data
75
   * the key will be the new key of the result-array
76
   *
77
   * e.g.:
78
   *    fetchArrayPair('some_id', 'some_value');
79
   *    // array(127 => 'some value', 128 => 'some other value')
80
   *
81
   * @param string $key
82
   * @param string $value
83
   *
84
   * @return array
85
   */
86 1
  public function fetchArrayPair($key, $value)
87
  {
88 1
    $arrayPair = array();
89 1
    $data = $this->fetchAllArray();
90
91 1
    foreach ($data as $_row) {
92 1
      if (isset($_row[$key], $_row[$value])) {
93 1
        $_key = $_row[$key];
94 1
        $_value = $_row[$value];
95 1
        $arrayPair[$_key] = $_value;
96 1
      }
97 1
    }
98
99 1
    return $arrayPair;
100
  }
101
102
  /**
103
   * Cast data into int, float or string.
104
   *
105
   * INFO: install / use "mysqlnd"-driver for better performance
106
   *
107
   * @param array|object $data
108
   *
109
   * @return array|false false on error
110
   */
111 20
  private function cast(&$data)
112
  {
113 20
    if (Helper::isMysqlndIsUsed() === true) {
114 20
      return $data;
115
    }
116
117
    // init
118
    static $fields = array();
119
    static $types = array();
120
121
    $result_hash = spl_object_hash($this->_result);
122
123
    if (!isset($fields[$result_hash])) {
124
      $fields[$result_hash] = mysqli_fetch_fields($this->_result);
125
    }
126
127
    if ($fields[$result_hash] === false) {
128
      return false;
129
    }
130
131
    if (!isset($types[$result_hash])) {
132
      foreach ($fields[$result_hash] as $field) {
133
        switch ($field->type) {
134
          case 3:
135
            $types[$result_hash][$field->name] = 'int';
136
            break;
137
          case 4:
138
            $types[$result_hash][$field->name] = 'float';
139
            break;
140
          default:
141
            $types[$result_hash][$field->name] = 'string';
142
            break;
143
        }
144
      }
145
    }
146
147
    if (is_array($data) === true) {
148 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...
149
        if (isset($data[$type_name])) {
150
          settype($data[$type_name], $type);
151
        }
152
      }
153
    } elseif (is_object($data)) {
154 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...
155
        if (isset($data->{$type_name})) {
156
          settype($data->{$type_name}, $type);
157
        }
158
      }
159
    }
160
161
    return $data;
162
  }
163
164
  /**
165
   * fetchAllArray
166
   *
167
   * @return array
168
   */
169 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...
170
  {
171
    // init
172 11
    $data = array();
173
174
    if (
175 11
        $this->_result
176 11
        &&
177 11
        !$this->is_empty()
178 11
    ) {
179 11
      $this->reset();
180
181
      /** @noinspection PhpAssignmentInConditionInspection */
182 11
      while ($row = mysqli_fetch_assoc($this->_result)) {
183 11
        $data[] = $this->cast($row);
184 11
      }
185 11
    }
186
187 11
    return $data;
188
  }
189
190
  /**
191
   * fetch all results, return via Arrayy
192
   *
193
   * @return Arrayy
194
   */
195 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...
196
  {
197
    // init
198 1
    $data = array();
199
200
    if (
201 1
        $this->_result
202 1
        &&
203 1
        !$this->is_empty()
204 1
    ) {
205 1
      $this->reset();
206
207
      /** @noinspection PhpAssignmentInConditionInspection */
208 1
      while ($row = mysqli_fetch_assoc($this->_result)) {
209 1
        $data[] = $this->cast($row);
210 1
      }
211 1
    }
212
213 1
    return Arrayy::create($data);
214
  }
215
216
  /**
217
   * is_empty
218
   *
219
   * @return bool
220
   */
221 13
  public function is_empty()
222
  {
223 13
    if ($this->num_rows > 0) {
224 13
      return false;
225
    } else {
226 1
      return true;
227
    }
228
  }
229
230
  /**
231
   * reset
232
   *
233
   * @return Result
234
   */
235 12
  public function reset()
236
  {
237 12
    if (!$this->is_empty()) {
238 12
      mysqli_data_seek($this->_result, 0);
239 12
    }
240
241 12
    return $this;
242
  }
243
244
  /**
245
   * json
246
   *
247
   * @return string
248
   */
249 1
  public function json()
250
  {
251 1
    $data = $this->fetchAllArray();
252
253 1
    return json_encode($data);
254
  }
255
256
  /**
257
   * __destruct
258
   *
259
   */
260 24
  public function __destruct()
261
  {
262 24
    $this->free();
263 24
  }
264
265
  /**
266
   * free
267
   */
268 24
  public function free()
269
  {
270 24
    mysqli_free_result($this->_result);
271 24
  }
272
273
  /**
274
   * get
275
   *
276
   * @return array|object|false false on error
277
   */
278 1
  public function get()
279
  {
280 1
    return $this->fetch();
281
  }
282
283
  /**
284
   * fetch (object -> not a array by default)
285
   *
286
   * @param $reset
287
   *
288
   * @return array|object|false false on error
289
   */
290 2
  public function fetch($reset = false)
291
  {
292 2
    $return = false;
293
294 2
    if ($this->_default_result_type === 'object') {
295 2
      $return = $this->fetchObject('', '', $reset);
296 2
    } elseif ($this->_default_result_type === 'array') {
297 2
      $return = $this->fetchArray($reset);
298 2
    }
299
300 2
    return $return;
301
  }
302
303
  /**
304
   * fetchObject
305
   *
306
   * @param string     $class
307
   * @param null|array $params
308
   * @param bool       $reset
309
   *
310
   * @return object|false false on error
311
   */
312 5
  public function fetchObject($class = '', $params = null, $reset = false)
313
  {
314 5
    if ($reset === true) {
315 1
      $this->reset();
316 1
    }
317
318 5
    if ($class && $params) {
319 1
      return ($row = mysqli_fetch_object($this->_result, $class, $params)) ? $row : false;
320
    }
321
322 5
    if ($class) {
323 1
      return ($row = mysqli_fetch_object($this->_result, $class)) ? $row : false;
324
    }
325
326 5
    return ($row = mysqli_fetch_object($this->_result)) ? $this->cast($row) : false;
327
  }
328
329
  /**
330
   * fetch as array
331
   *
332
   * @param bool $reset
333
   *
334
   * @return array|false false on error
335
   */
336 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...
337
  {
338 9
    if ($reset === true) {
339 1
      $this->reset();
340 1
    }
341
342 9
    $row = mysqli_fetch_assoc($this->_result);
343 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...
344 9
      return $this->cast($row);
345
    }
346
347
    return false;
348
  }
349
350
  /**
351
   * fetch as Arrayy-Object
352
   *
353
   * @param bool $reset
354
   *
355
   * @return Arrayy|false false on error
356
   */
357 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...
358
  {
359 1
    if ($reset === true) {
360
      $this->reset();
361
    }
362
363 1
    $row = mysqli_fetch_assoc($this->_result);
364 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...
365 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...
366
    }
367
368
    return false;
369
  }
370
371
  /**
372
   * getAll
373
   *
374
   * @return array
375
   */
376 1
  public function getAll()
377
  {
378 1
    return $this->fetchAll();
379
  }
380
381
  /**
382
   * fetchAll
383
   *
384
   * @return array
385
   */
386 2
  public function fetchAll()
387
  {
388 2
    $return = array();
389
390 2
    if ($this->_default_result_type === 'object') {
391 2
      $return = $this->fetchAllObject();
392 2
    } elseif ($this->_default_result_type === 'array') {
393 1
      $return = $this->fetchAllArray();
394 1
    }
395
396 2
    return $return;
397
  }
398
399
  /**
400
   * fetchAllObject
401
   *
402
   * @param string     $class
403
   * @param null|array $params
404
   *
405
   * @return array
406
   */
407 3
  public function fetchAllObject($class = '', $params = null)
408
  {
409
    // init
410 3
    $data = array();
411
412 3
    if (!$this->is_empty()) {
413 3
      $this->reset();
414
415 3
      if ($class && $params) {
416
        /** @noinspection PhpAssignmentInConditionInspection */
417 1
        while ($row = mysqli_fetch_object($this->_result, $class, $params)) {
418 1
          $data[] = $row;
419 1
        }
420 3
      } elseif ($class) {
421
        /** @noinspection PhpAssignmentInConditionInspection */
422 1
        while ($row = mysqli_fetch_object($this->_result, $class)) {
423 1
          $data[] = $row;
424 1
        }
425 1
      } else {
426
        /** @noinspection PhpAssignmentInConditionInspection */
427 3
        while ($row = mysqli_fetch_object($this->_result)) {
428 3
          $data[] = $this->cast($row);
429 3
        }
430
      }
431 3
    }
432
433 3
    return $data;
434
  }
435
436
  /**
437
   * getObject
438
   *
439
   * @return array of mysql-objects
440
   */
441 1
  public function getObject()
442
  {
443 1
    return $this->fetchAllObject();
444
  }
445
446
  /**
447
   * getArray
448
   *
449
   * @return array
450
   */
451 1
  public function getArray()
452
  {
453 1
    return $this->fetchAllArray();
454
  }
455
456
  /**
457
   * getColumn
458
   *
459
   * @param $key
460
   *
461
   * @return string
462
   */
463 1
  public function getColumn($key)
464
  {
465 1
    return $this->fetchColumn($key);
466
  }
467
468
  /**
469
   * fetchColumn
470
   *
471
   * @param string $column
472
   *
473
   * @return string empty string if the $column wasn't found
474
   */
475 2
  public function fetchColumn($column = '')
476
  {
477 2
    $columnData = '';
478 2
    $data = $this->fetchAllArray();
479
480 2
    foreach ($data as $_row) {
481 2
      if (isset($_row[$column])) {
482 2
        $columnData = $_row[$column];
483 2
      }
484 2
    }
485
486 2
    return $columnData;
487
  }
488
489
  /**
490
   * get the num-rows as string
491
   *
492
   * @return string
493
   */
494
  public function __toString()
495
  {
496
    return (string)$this->num_rows;
497
  }
498
}
499