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:
Complex classes like Result often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Result, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 10 | final class Result implements \Countable, \SeekableIterator, \ArrayAccess |
||
| 11 | { |
||
| 12 | const MYSQL_TYPE_BIT = 16; |
||
| 13 | |||
| 14 | const MYSQL_TYPE_BLOB = 252; |
||
| 15 | |||
| 16 | const MYSQL_TYPE_DATE = 10; |
||
| 17 | |||
| 18 | const MYSQL_TYPE_DATETIME = 12; |
||
| 19 | |||
| 20 | const MYSQL_TYPE_DECIMAL = 0; |
||
| 21 | |||
| 22 | const MYSQL_TYPE_DOUBLE = 5; |
||
| 23 | |||
| 24 | const MYSQL_TYPE_ENUM = 247; |
||
| 25 | |||
| 26 | const MYSQL_TYPE_FLOAT = 4; |
||
| 27 | |||
| 28 | const MYSQL_TYPE_GEOMETRY = 255; |
||
| 29 | |||
| 30 | const MYSQL_TYPE_INT24 = 9; |
||
| 31 | |||
| 32 | const MYSQL_TYPE_JSON = 245; |
||
| 33 | |||
| 34 | const MYSQL_TYPE_LONG = 3; |
||
| 35 | |||
| 36 | const MYSQL_TYPE_LONGLONG = 8; |
||
| 37 | |||
| 38 | const MYSQL_TYPE_LONG_BLOB = 251; |
||
| 39 | |||
| 40 | const MYSQL_TYPE_MEDIUM_BLOB = 250; |
||
| 41 | |||
| 42 | const MYSQL_TYPE_NEWDATE = 14; |
||
| 43 | |||
| 44 | const MYSQL_TYPE_NEWDECIMAL = 246; |
||
| 45 | |||
| 46 | const MYSQL_TYPE_NULL = 6; |
||
| 47 | |||
| 48 | const MYSQL_TYPE_SET = 248; |
||
| 49 | |||
| 50 | const MYSQL_TYPE_SHORT = 2; |
||
| 51 | |||
| 52 | const MYSQL_TYPE_STRING = 254; |
||
| 53 | |||
| 54 | const MYSQL_TYPE_TIME = 11; |
||
| 55 | |||
| 56 | const MYSQL_TYPE_TIMESTAMP = 7; |
||
| 57 | |||
| 58 | const MYSQL_TYPE_TINY = 1; |
||
| 59 | |||
| 60 | const MYSQL_TYPE_TINY_BLOB = 249; |
||
| 61 | |||
| 62 | const MYSQL_TYPE_VARCHAR = 15; |
||
| 63 | |||
| 64 | const MYSQL_TYPE_VAR_STRING = 253; |
||
| 65 | |||
| 66 | const MYSQL_TYPE_YEAR = 13; |
||
| 67 | |||
| 68 | const RESULT_TYPE_ARRAY = 'array'; |
||
| 69 | |||
| 70 | const RESULT_TYPE_ARRAYY = 'Arrayy'; |
||
| 71 | |||
| 72 | const RESULT_TYPE_OBJECT = 'object'; |
||
| 73 | |||
| 74 | const RESULT_TYPE_YIELD = 'yield'; |
||
| 75 | |||
| 76 | /** |
||
| 77 | * @var int |
||
| 78 | */ |
||
| 79 | public $num_rows; |
||
| 80 | |||
| 81 | /** |
||
| 82 | * @var string |
||
| 83 | */ |
||
| 84 | public $sql; |
||
| 85 | |||
| 86 | /** |
||
| 87 | * @var \Doctrine\DBAL\Driver\Statement|\mysqli_result |
||
| 88 | */ |
||
| 89 | private $_result; |
||
| 90 | |||
| 91 | /** |
||
| 92 | * @var int |
||
| 93 | */ |
||
| 94 | private $current_row; |
||
| 95 | |||
| 96 | /** |
||
| 97 | * @var \Closure|null |
||
| 98 | */ |
||
| 99 | private $_mapper; |
||
| 100 | |||
| 101 | /** |
||
| 102 | * @var string |
||
| 103 | */ |
||
| 104 | private $_default_result_type = self::RESULT_TYPE_OBJECT; |
||
| 105 | |||
| 106 | /** |
||
| 107 | * @var \mysqli_stmt|null |
||
| 108 | */ |
||
| 109 | private $doctrineMySQLiStmt; |
||
| 110 | |||
| 111 | /** |
||
| 112 | * @var \Doctrine\DBAL\Driver\PDOStatement|null |
||
| 113 | */ |
||
| 114 | private $doctrinePdoStmt; |
||
| 115 | |||
| 116 | /** |
||
| 117 | * @var int |
||
| 118 | */ |
||
| 119 | private $doctrinePdoStmtDataSeekFake = 0; |
||
| 120 | |||
| 121 | /** |
||
| 122 | * @var bool |
||
| 123 | */ |
||
| 124 | private $doctrinePdoStmtDataSeekInit = false; |
||
| 125 | |||
| 126 | /** |
||
| 127 | * @var array |
||
| 128 | */ |
||
| 129 | private $doctrinePdoStmtDataSeekFakeCache = []; |
||
| 130 | |||
| 131 | /** |
||
| 132 | * Result constructor. |
||
| 133 | * |
||
| 134 | * @param string $sql |
||
| 135 | * @param \Doctrine\DBAL\Driver\Statement|\mysqli_result $result |
||
| 136 | * @param \Closure $mapper Optional callback mapper for the "fetchCallable()" method |
||
| 137 | */ |
||
| 138 | 99 | public function __construct(string $sql, $result, \Closure $mapper = null) |
|
| 139 | { |
||
| 140 | 99 | $this->sql = $sql; |
|
| 141 | |||
| 142 | if ( |
||
| 143 | 99 | !$result instanceof \mysqli_result |
|
| 144 | && |
||
| 145 | 99 | !$result instanceof \Doctrine\DBAL\Driver\Statement |
|
| 146 | ) { |
||
| 147 | throw new \InvalidArgumentException('$result must be ' . \mysqli_result::class . ' or ' . \Doctrine\DBAL\Driver\Statement::class . ' !'); |
||
| 148 | } |
||
| 149 | |||
| 150 | 99 | $this->_result = $result; |
|
| 151 | |||
| 152 | 99 | if ($this->_result instanceof \Doctrine\DBAL\Driver\Statement) { |
|
| 153 | if (\method_exists($this->_result, 'getWrappedStatement')) { |
||
| 154 | throw new \InvalidArgumentException('$result (' . \Doctrine\DBAL\Driver\Statement::class . ') must implement "getWrappedStatement()"!'); |
||
| 155 | } |
||
| 156 | |||
| 157 | $doctrineDriver = $this->_result->getWrappedStatement(); |
||
|
|
|||
| 158 | |||
| 159 | if ($doctrineDriver instanceof \Doctrine\DBAL\Driver\PDOStatement) { |
||
| 160 | $this->doctrinePdoStmt = $doctrineDriver; |
||
| 161 | } |
||
| 162 | |||
| 163 | if ($doctrineDriver instanceof \Doctrine\DBAL\Driver\Mysqli\MysqliStatement) { |
||
| 164 | // try to get the mysqli driver from doctrine |
||
| 165 | $reflectionTmp = new \ReflectionClass($doctrineDriver); |
||
| 166 | $propertyTmp = $reflectionTmp->getProperty('_stmt'); |
||
| 167 | $propertyTmp->setAccessible(true); |
||
| 168 | $this->doctrineMySQLiStmt = $propertyTmp->getValue($doctrineDriver); |
||
| 169 | } |
||
| 170 | |||
| 171 | $this->num_rows = $this->_result->rowCount(); |
||
| 172 | } else { |
||
| 173 | 99 | $this->num_rows = (int) $this->_result->num_rows; |
|
| 174 | } |
||
| 175 | |||
| 176 | 99 | $this->current_row = 0; |
|
| 177 | |||
| 178 | 99 | $this->_mapper = $mapper; |
|
| 179 | 99 | } |
|
| 180 | |||
| 181 | /** |
||
| 182 | * __destruct |
||
| 183 | */ |
||
| 184 | 98 | public function __destruct() |
|
| 188 | |||
| 189 | /** |
||
| 190 | * Runs a user-provided callback with the MySQLi_Result object given as |
||
| 191 | * argument and returns the result, or returns the MySQLi_Result object if |
||
| 192 | * called without an argument. |
||
| 193 | * |
||
| 194 | * @param callable $callback User-provided callback (optional) |
||
| 195 | * |
||
| 196 | * @return \Doctrine\DBAL\Driver\Statement|mixed|\mysqli_result |
||
| 197 | */ |
||
| 198 | 2 | public function __invoke(callable $callback = null) |
|
| 206 | |||
| 207 | /** |
||
| 208 | * Get the current "num_rows" as string. |
||
| 209 | * |
||
| 210 | * @return string |
||
| 211 | */ |
||
| 212 | public function __toString() |
||
| 216 | |||
| 217 | /** |
||
| 218 | * Cast data into int, float or string. |
||
| 219 | * |
||
| 220 | * <p> |
||
| 221 | * <br /> |
||
| 222 | * INFO: install / use "mysqlnd"-driver for better performance |
||
| 223 | * </p> |
||
| 224 | * |
||
| 225 | * @param array|object $data |
||
| 226 | * |
||
| 227 | * @return array|false|object |
||
| 228 | * <p><strong>false</strong> on error</p> |
||
| 229 | */ |
||
| 230 | 67 | private function &cast(&$data) |
|
| 306 | |||
| 307 | /** |
||
| 308 | * Countable interface implementation. |
||
| 309 | * |
||
| 310 | * @return int The number of rows in the result |
||
| 311 | */ |
||
| 312 | 2 | public function count(): int |
|
| 316 | |||
| 317 | /** |
||
| 318 | * Iterator interface implementation. |
||
| 319 | * |
||
| 320 | * @return mixed The current element |
||
| 321 | */ |
||
| 322 | 5 | public function current() |
|
| 326 | |||
| 327 | /** |
||
| 328 | * Iterator interface implementation. |
||
| 329 | * |
||
| 330 | * @return int The current element key (row index; zero-based) |
||
| 331 | */ |
||
| 332 | 1 | public function key(): int |
|
| 336 | |||
| 337 | /** |
||
| 338 | * Iterator interface implementation. |
||
| 339 | * |
||
| 340 | * @return void |
||
| 341 | */ |
||
| 342 | 5 | public function next() |
|
| 346 | |||
| 347 | /** |
||
| 348 | * Iterator interface implementation. |
||
| 349 | * |
||
| 350 | * @param int $row Row position to rewind to; defaults to 0 |
||
| 351 | * |
||
| 352 | * @return void |
||
| 353 | */ |
||
| 354 | 11 | public function rewind($row = 0) |
|
| 360 | |||
| 361 | /** |
||
| 362 | * Moves the internal pointer to the specified row position. |
||
| 363 | * |
||
| 364 | * @param int $row <p>Row position; zero-based and set to 0 by default</p> |
||
| 365 | * |
||
| 366 | * @return bool |
||
| 367 | * <p>true on success, false otherwise</p> |
||
| 368 | */ |
||
| 369 | 19 | public function seek($row = 0): bool |
|
| 397 | |||
| 398 | /** |
||
| 399 | * Iterator interface implementation. |
||
| 400 | * |
||
| 401 | * @return bool |
||
| 402 | * <p>true if the current index is valid, false otherwise</p> |
||
| 403 | */ |
||
| 404 | 5 | public function valid(): bool |
|
| 408 | |||
| 409 | /** |
||
| 410 | * Fetch. |
||
| 411 | * |
||
| 412 | * <p> |
||
| 413 | * <br /> |
||
| 414 | * INFO: this will return an object by default, not an array<br /> |
||
| 415 | * and you can change the behaviour via "Result->setDefaultResultType()" |
||
| 416 | * </p> |
||
| 417 | * |
||
| 418 | * @param bool $reset optional <p>Reset the \mysqli_result counter.</p> |
||
| 419 | * |
||
| 420 | * @return array|false|object |
||
| 421 | * <p><strong>false</strong> on error</p> |
||
| 422 | */ |
||
| 423 | 3 | public function &fetch(bool $reset = false) |
|
| 440 | |||
| 441 | /** |
||
| 442 | * Fetch all results. |
||
| 443 | * |
||
| 444 | * <p> |
||
| 445 | * <br /> |
||
| 446 | * INFO: this will return an object by default, not an array<br /> |
||
| 447 | * and you can change the behaviour via "Result->setDefaultResultType()" |
||
| 448 | * </p> |
||
| 449 | * |
||
| 450 | * @return array |
||
| 451 | */ |
||
| 452 | 3 | public function &fetchAll(): array |
|
| 469 | |||
| 470 | /** |
||
| 471 | * Fetch all results as array. |
||
| 472 | * |
||
| 473 | * @return array |
||
| 474 | */ |
||
| 475 | 17 | View Code Duplication | public function &fetchAllArray(): array |
| 493 | |||
| 494 | /** |
||
| 495 | * Fetch all results as "Arrayy"-object. |
||
| 496 | * |
||
| 497 | * @return \Arrayy\Arrayy |
||
| 498 | */ |
||
| 499 | 8 | View Code Duplication | public function &fetchAllArrayy(): \Arrayy\Arrayy |
| 517 | |||
| 518 | /** |
||
| 519 | * Fetch all results as "Arrayy"-object. |
||
| 520 | * |
||
| 521 | * @return \Arrayy\Arrayy |
||
| 522 | */ |
||
| 523 | 11 | public function fetchAllArrayyYield(): \Arrayy\Arrayy |
|
| 540 | |||
| 541 | /** |
||
| 542 | * Fetch a single column as an 1-dimension array. |
||
| 543 | * |
||
| 544 | * @param string $column |
||
| 545 | * @param bool $skipNullValues <p>Skip "NULL"-values. | default: false</p> |
||
| 546 | * |
||
| 547 | * @return array |
||
| 548 | * <p>Return an empty array if the "$column" wasn't found</p> |
||
| 549 | */ |
||
| 550 | 5 | public function fetchAllColumn(string $column, bool $skipNullValues = false): array |
|
| 562 | |||
| 563 | /** |
||
| 564 | * Fetch all results as array with objects. |
||
| 565 | * |
||
| 566 | * @param object|string|null $class <p> |
||
| 567 | * <strong>string</strong>: create a new object (with optional constructor |
||
| 568 | * parameter)<br> |
||
| 569 | * <strong>object</strong>: use a object and fill the the data into |
||
| 570 | * </p> |
||
| 571 | * @param array|null $params optional |
||
| 572 | * <p> |
||
| 573 | * An array of parameters to pass to the constructor, used if $class is a |
||
| 574 | * string. |
||
| 575 | * </p> |
||
| 576 | * |
||
| 577 | * @return object[] |
||
| 578 | * |
||
| 579 | * @psalm-param class-string|object|null $class |
||
| 580 | * @psalm-param array<int, mixed>|null $params |
||
| 581 | */ |
||
| 582 | 6 | public function &fetchAllObject( |
|
| 595 | |||
| 596 | /** |
||
| 597 | * Fetch all results as "\Generator" via yield. |
||
| 598 | * |
||
| 599 | * @param object|string|null $class <p> |
||
| 600 | * <strong>string</strong>: create a new object (with optional constructor |
||
| 601 | * parameter)<br> |
||
| 602 | * <strong>object</strong>: use a object and fill the the data into |
||
| 603 | * </p> |
||
| 604 | * @param array|null $params optional |
||
| 605 | * <p> |
||
| 606 | * An array of parameters to pass to the constructor, used if $class is a |
||
| 607 | * string. |
||
| 608 | * </p> |
||
| 609 | * |
||
| 610 | * @return \Generator |
||
| 611 | * @psalm-param class-string|object|null $class |
||
| 612 | * @psalm-param array<int, mixed>|null $params |
||
| 613 | */ |
||
| 614 | 14 | public function &fetchAllYield( |
|
| 664 | |||
| 665 | /** |
||
| 666 | * Fetch as array. |
||
| 667 | * |
||
| 668 | * @param bool $reset |
||
| 669 | * |
||
| 670 | * @return array|false |
||
| 671 | * <p><strong>false</strong> on error</p> |
||
| 672 | */ |
||
| 673 | 30 | public function fetchArray(bool $reset = false) |
|
| 694 | |||
| 695 | /** |
||
| 696 | * Fetch data as a key/value pair array. |
||
| 697 | * |
||
| 698 | * <p> |
||
| 699 | * <br /> |
||
| 700 | * INFO: both "key" and "value" must exists in the fetched data |
||
| 701 | * the key will be the new key of the result-array |
||
| 702 | * <br /><br /> |
||
| 703 | * </p> |
||
| 704 | * |
||
| 705 | * e.g.: |
||
| 706 | * <code> |
||
| 707 | * fetchArrayPair('some_id', 'some_value'); |
||
| 708 | * // array(127 => 'some value', 128 => 'some other value') |
||
| 709 | * </code> |
||
| 710 | * |
||
| 711 | * @param string $key |
||
| 712 | * @param string $value |
||
| 713 | * |
||
| 714 | * @return \Arrayy\Arrayy |
||
| 715 | */ |
||
| 716 | 3 | public function fetchArrayPair(string $key, string $value): \Arrayy\Arrayy |
|
| 717 | { |
||
| 718 | // init |
||
| 719 | 3 | $arrayPair = new \Arrayy\Arrayy(); |
|
| 720 | 3 | $data = $this->fetchAllArrayyYield(); |
|
| 721 | |||
| 722 | 3 | foreach ($data as $_row) { |
|
| 723 | if ( |
||
| 724 | 3 | \array_key_exists($key, $_row) |
|
| 725 | && |
||
| 726 | 3 | \array_key_exists($value, $_row) |
|
| 727 | ) { |
||
| 728 | $_key = $_row[$key]; |
||
| 729 | $_value = $_row[$value]; |
||
| 730 | 3 | $arrayPair[$_key] = $_value; |
|
| 731 | } |
||
| 732 | } |
||
| 733 | |||
| 734 | 3 | return $arrayPair; |
|
| 735 | } |
||
| 736 | |||
| 737 | /** |
||
| 738 | * Fetch as "Arrayy"-object. |
||
| 739 | * |
||
| 740 | * @param bool $reset optional <p>Reset the \mysqli_result counter.</p> |
||
| 741 | * |
||
| 742 | * @return \Arrayy\Arrayy|false |
||
| 743 | * <p><strong>false</strong> on error</p> |
||
| 744 | */ |
||
| 745 | 6 | public function fetchArrayy(bool $reset = false) |
|
| 762 | |||
| 763 | /** |
||
| 764 | * Fetches a row or a single column within a row. Returns null if there are |
||
| 765 | * no more rows in the result. |
||
| 766 | * |
||
| 767 | * @param int $row The row number (optional) |
||
| 768 | * @param string $column The column name (optional) |
||
| 769 | * |
||
| 770 | * @return mixed An associative array or a scalar value |
||
| 771 | */ |
||
| 772 | 14 | public function fetchCallable(int $row = null, string $column = null) |
|
| 802 | |||
| 803 | /** |
||
| 804 | * Fetch a single column as string (or as 1-dimension array). |
||
| 805 | * |
||
| 806 | * @param string $column |
||
| 807 | * @param bool $skipNullValues <p>Skip "NULL"-values. | default: true</p> |
||
| 808 | * @param bool $asArray <p>Get all values and not only the last one. | default: false</p> |
||
| 809 | * |
||
| 810 | * @return array|string |
||
| 811 | * <p>Return a empty string or an empty array if the "$column" wasn't found, depend on |
||
| 812 | * "$asArray"</p> |
||
| 813 | */ |
||
| 814 | 6 | public function &fetchColumn( |
|
| 860 | |||
| 861 | /** |
||
| 862 | * Return rows of field information in a result set. |
||
| 863 | * |
||
| 864 | * @param bool $as_array Return each field info as array; defaults to false |
||
| 865 | * |
||
| 866 | * @return array |
||
| 867 | * <p>Array of field information each as an associative array.</p> |
||
| 868 | */ |
||
| 869 | 1 | public function &fetchFields(bool $as_array = false): array |
|
| 891 | |||
| 892 | /** |
||
| 893 | * Returns all rows at once as a grouped array of scalar values or arrays. |
||
| 894 | * |
||
| 895 | * @param string $group The column name to use for grouping |
||
| 896 | * @param string $column The column name to use as values (optional) |
||
| 897 | * |
||
| 898 | * @return array |
||
| 899 | * <p>A grouped array of scalar values or arrays.</p> |
||
| 900 | */ |
||
| 901 | 1 | View Code Duplication | public function &fetchGroups(string $group, string $column = null): array |
| 902 | { |
||
| 903 | // init |
||
| 904 | 1 | $groups = []; |
|
| 905 | 1 | $pos = $this->current_row; |
|
| 906 | |||
| 907 | 1 | foreach ($this->fetchAllArrayyYield() as $row) { |
|
| 908 | 1 | if (!\array_key_exists($group, $row)) { |
|
| 909 | 1 | continue; |
|
| 910 | } |
||
| 911 | |||
| 912 | if ($column !== null) { |
||
| 913 | if (!\array_key_exists($column, $row)) { |
||
| 914 | continue; |
||
| 915 | } |
||
| 916 | |||
| 917 | $groups[$row[$group]][] = $row[$column]; |
||
| 918 | } else { |
||
| 919 | $groups[$row[$group]][] = $row; |
||
| 920 | } |
||
| 921 | } |
||
| 922 | |||
| 923 | 1 | $this->rewind($pos); |
|
| 924 | |||
| 925 | 1 | return $groups; |
|
| 926 | } |
||
| 927 | |||
| 928 | /** |
||
| 929 | * Fetch as object. |
||
| 930 | * |
||
| 931 | * @param object|string|null $class <p> |
||
| 932 | * <strong>string</strong>: create a new object (with optional constructor |
||
| 933 | * parameter)<br> |
||
| 934 | * <strong>object</strong>: use a object and fill the the data into |
||
| 935 | * </p> |
||
| 936 | * @param array|null $params optional |
||
| 937 | * <p> |
||
| 938 | * An array of parameters to pass to the constructor, used if $class is a |
||
| 939 | * string. |
||
| 940 | * </p> |
||
| 941 | * @param bool $reset optional <p>Reset the \mysqli_result counter.</p> |
||
| 942 | * |
||
| 943 | * @return false|object |
||
| 944 | * <p><strong>false</strong> on error</p> |
||
| 945 | * |
||
| 946 | * @psalm-param class-string|object|null $class |
||
| 947 | * @psalm-param array<int, mixed>|null $params |
||
| 948 | */ |
||
| 949 | 18 | View Code Duplication | public function &fetchObject( |
| 999 | |||
| 1000 | /** |
||
| 1001 | * Returns all rows at once as key-value pairs. |
||
| 1002 | * |
||
| 1003 | * @param string $key The column name to use as keys |
||
| 1004 | * @param string $column The column name to use as values (optional) |
||
| 1005 | * |
||
| 1006 | * @return array |
||
| 1007 | * <p>An array of key-value pairs.</p> |
||
| 1008 | */ |
||
| 1009 | View Code Duplication | public function fetchPairs(string $key, string $column = null): array |
|
| 1010 | { |
||
| 1011 | // init |
||
| 1012 | $pairs = []; |
||
| 1013 | $pos = $this->current_row; |
||
| 1014 | |||
| 1015 | foreach ($this->fetchAllArrayyYield() as $row) { |
||
| 1016 | if (!\array_key_exists($key, $row)) { |
||
| 1017 | continue; |
||
| 1018 | } |
||
| 1019 | |||
| 1020 | if ($column !== null) { |
||
| 1021 | if (!\array_key_exists($column, $row)) { |
||
| 1022 | continue; |
||
| 1023 | } |
||
| 1024 | |||
| 1025 | $pairs[$row[$key]] = $row[$column]; |
||
| 1026 | } else { |
||
| 1027 | $pairs[$row[$key]] = $row; |
||
| 1028 | } |
||
| 1029 | } |
||
| 1030 | |||
| 1031 | $this->rewind($pos); |
||
| 1032 | |||
| 1033 | return $pairs; |
||
| 1034 | } |
||
| 1035 | |||
| 1036 | /** |
||
| 1037 | * Returns all rows at once, transposed as an array of arrays. Instead of |
||
| 1038 | * returning rows of columns, this method returns columns of rows. |
||
| 1039 | * |
||
| 1040 | * @param string $column The column name to use as keys (optional) |
||
| 1041 | * |
||
| 1042 | * @return array |
||
| 1043 | * <p>A transposed array of arrays</p> |
||
| 1044 | */ |
||
| 1045 | 1 | public function fetchTranspose(string $column = null) |
|
| 1071 | |||
| 1072 | /** |
||
| 1073 | * Fetch as "\Generator" via yield. |
||
| 1074 | * |
||
| 1075 | * @param object|string|null $class <p> |
||
| 1076 | * <strong>string</strong>: create a new object (with optional constructor |
||
| 1077 | * parameter)<br> |
||
| 1078 | * <strong>object</strong>: use a object and fill the the data into |
||
| 1079 | * </p> |
||
| 1080 | * @param array|null $params optional |
||
| 1081 | * <p> |
||
| 1082 | * An array of parameters to pass to the constructor, used if $class is a |
||
| 1083 | * string. |
||
| 1084 | * </p> |
||
| 1085 | * @param bool $reset optional <p>Reset the \mysqli_result counter.</p> |
||
| 1086 | * |
||
| 1087 | * @return \Generator |
||
| 1088 | * |
||
| 1089 | * @psalm-param class-string|object|null $class |
||
| 1090 | * @psalm-param array<int, mixed>|null $params |
||
| 1091 | */ |
||
| 1092 | 4 | View Code Duplication | public function fetchYield( |
| 1140 | |||
| 1141 | /** |
||
| 1142 | * @return mixed|null |
||
| 1143 | */ |
||
| 1144 | 75 | private function fetch_assoc() |
|
| 1181 | |||
| 1182 | /** |
||
| 1183 | * @return array|false |
||
| 1184 | */ |
||
| 1185 | 1 | private function fetch_fields() |
|
| 1232 | |||
| 1233 | /** |
||
| 1234 | * Returns the first row element from the result. |
||
| 1235 | * |
||
| 1236 | * @param string $column The column name to use as value (optional) |
||
| 1237 | * |
||
| 1238 | * @return mixed |
||
| 1239 | * <p>A row array or a single scalar value</p> |
||
| 1240 | */ |
||
| 1241 | 3 | public function first(string $column = null) |
|
| 1249 | |||
| 1250 | /** |
||
| 1251 | * free the memory |
||
| 1252 | * |
||
| 1253 | * @return bool |
||
| 1254 | */ |
||
| 1255 | 98 | public function free() |
|
| 1276 | |||
| 1277 | /** |
||
| 1278 | * alias for "Result->fetch()" |
||
| 1279 | * |
||
| 1280 | * @return array|false|object |
||
| 1281 | * <p><strong>false</strong> on error</p> |
||
| 1282 | * |
||
| 1283 | * @see Result::fetch() |
||
| 1284 | */ |
||
| 1285 | public function get() |
||
| 1286 | { |
||
| 1287 | return $this->fetch(); |
||
| 1288 | } |
||
| 1289 | |||
| 1290 | /** |
||
| 1291 | * alias for "Result->fetchAll()" |
||
| 1292 | * |
||
| 1293 | * @return array |
||
| 1294 | * |
||
| 1295 | * @see Result::fetchAll() |
||
| 1296 | */ |
||
| 1297 | public function getAll(): array |
||
| 1298 | { |
||
| 1299 | return $this->fetchAll(); |
||
| 1300 | } |
||
| 1301 | |||
| 1302 | /** |
||
| 1303 | * alias for "Result->fetchAllColumn()" |
||
| 1304 | * |
||
| 1305 | * @param string $column |
||
| 1306 | * @param bool $skipNullValues |
||
| 1307 | * |
||
| 1308 | * @return array |
||
| 1309 | * |
||
| 1310 | * @see Result::fetchAllColumn() |
||
| 1311 | */ |
||
| 1312 | public function getAllColumn(string $column, bool $skipNullValues = false): array |
||
| 1316 | |||
| 1317 | /** |
||
| 1318 | * alias for "Result->fetchAllArray()" |
||
| 1319 | * |
||
| 1320 | * @return array |
||
| 1321 | * |
||
| 1322 | * @see Result::fetchAllArray() |
||
| 1323 | */ |
||
| 1324 | 1 | public function getArray(): array |
|
| 1328 | |||
| 1329 | /** |
||
| 1330 | * alias for "Result->fetchAllArrayy()" |
||
| 1331 | * |
||
| 1332 | * @return \Arrayy\Arrayy |
||
| 1333 | * |
||
| 1334 | * @see Result::fetchAllArrayy() |
||
| 1335 | */ |
||
| 1336 | public function getArrayy(): \Arrayy\Arrayy |
||
| 1340 | |||
| 1341 | /** |
||
| 1342 | * alias for "Result->fetchColumn()" |
||
| 1343 | * |
||
| 1344 | * @param string $column |
||
| 1345 | * @param bool $asArray |
||
| 1346 | * @param bool $skipNullValues |
||
| 1347 | * |
||
| 1348 | * @return array|string |
||
| 1349 | * <p>Return a empty string or an empty array if the "$column" wasn't found, depend on |
||
| 1350 | * "$asArray"</p> |
||
| 1351 | * |
||
| 1352 | * @see Result::fetchColumn() |
||
| 1353 | */ |
||
| 1354 | public function getColumn( |
||
| 1355 | string $column, |
||
| 1356 | bool $skipNullValues = true, |
||
| 1357 | bool $asArray = false |
||
| 1358 | ) { |
||
| 1359 | return $this->fetchColumn( |
||
| 1360 | $column, |
||
| 1361 | $skipNullValues, |
||
| 1362 | $asArray |
||
| 1363 | ); |
||
| 1364 | } |
||
| 1365 | |||
| 1366 | /** |
||
| 1367 | * @return string |
||
| 1368 | */ |
||
| 1369 | public function getDefaultResultType(): string |
||
| 1370 | { |
||
| 1371 | return $this->_default_result_type; |
||
| 1372 | } |
||
| 1373 | |||
| 1374 | /** |
||
| 1375 | * alias for "Result->fetchAllObject()" |
||
| 1376 | * |
||
| 1377 | * @return array of mysql-objects |
||
| 1378 | * |
||
| 1379 | * @see Result::fetchAllObject() |
||
| 1380 | */ |
||
| 1381 | public function getObject(): array |
||
| 1382 | { |
||
| 1383 | return $this->fetchAllObject(); |
||
| 1384 | } |
||
| 1385 | |||
| 1386 | /** |
||
| 1387 | * alias for "Result->fetchAllYield()" |
||
| 1388 | * |
||
| 1389 | * @return \Generator |
||
| 1390 | * |
||
| 1391 | * @see Result::fetchAllYield() |
||
| 1392 | */ |
||
| 1393 | 1 | public function getYield(): \Generator |
|
| 1397 | |||
| 1398 | /** |
||
| 1399 | * Check if the result is empty. |
||
| 1400 | * |
||
| 1401 | * @return bool |
||
| 1402 | */ |
||
| 1403 | 40 | public function is_empty(): bool |
|
| 1407 | |||
| 1408 | /** |
||
| 1409 | * Fetch all results as "json"-string. |
||
| 1410 | * |
||
| 1411 | * @return false|string |
||
| 1412 | */ |
||
| 1413 | 3 | public function json() |
|
| 1419 | |||
| 1420 | /** |
||
| 1421 | * Returns the last row element from the result. |
||
| 1422 | * |
||
| 1423 | * @param string $column The column name to use as value (optional) |
||
| 1424 | * |
||
| 1425 | * @return mixed A row array or a single scalar value |
||
| 1426 | */ |
||
| 1427 | 3 | public function last(string $column = null) |
|
| 1435 | |||
| 1436 | /** |
||
| 1437 | * Set the mapper... |
||
| 1438 | * |
||
| 1439 | * @param \Closure $callable |
||
| 1440 | * |
||
| 1441 | * @return $this |
||
| 1442 | */ |
||
| 1443 | 1 | public function map(\Closure $callable): self |
|
| 1449 | |||
| 1450 | /** |
||
| 1451 | * Alias of count(). Deprecated. |
||
| 1452 | * |
||
| 1453 | * @return int |
||
| 1454 | * <p>The number of rows in the result.</p> |
||
| 1455 | */ |
||
| 1456 | 1 | public function num_rows(): int |
|
| 1460 | |||
| 1461 | /** |
||
| 1462 | * ArrayAccess interface implementation. |
||
| 1463 | * |
||
| 1464 | * @param int $offset <p>Offset number</p> |
||
| 1465 | * |
||
| 1466 | * @return bool |
||
| 1467 | * <p>true if offset exists, false otherwise.</p> |
||
| 1468 | */ |
||
| 1469 | 1 | public function offsetExists($offset): bool |
|
| 1473 | |||
| 1474 | /** |
||
| 1475 | * ArrayAccess interface implementation. |
||
| 1476 | * |
||
| 1477 | * @param int $offset Offset number |
||
| 1478 | * |
||
| 1479 | * @return mixed |
||
| 1480 | */ |
||
| 1481 | 1 | public function offsetGet($offset) |
|
| 1489 | |||
| 1490 | /** |
||
| 1491 | * ArrayAccess interface implementation. Not implemented by design. |
||
| 1492 | * |
||
| 1493 | * @param mixed $offset |
||
| 1494 | * @param mixed $value |
||
| 1495 | * |
||
| 1496 | * @return void |
||
| 1497 | */ |
||
| 1498 | public function offsetSet($offset, $value) |
||
| 1501 | |||
| 1502 | /** |
||
| 1503 | * ArrayAccess interface implementation. Not implemented by design. |
||
| 1504 | * |
||
| 1505 | * @param mixed $offset |
||
| 1506 | * |
||
| 1507 | * @return void |
||
| 1508 | */ |
||
| 1509 | public function offsetUnset($offset) |
||
| 1512 | |||
| 1513 | /** |
||
| 1514 | * Reset the offset (data_seek) for the results. |
||
| 1515 | * |
||
| 1516 | * @return Result |
||
| 1517 | */ |
||
| 1518 | 37 | public function reset(): self |
|
| 1534 | |||
| 1535 | /** |
||
| 1536 | * You can set the default result-type to Result::RESULT_TYPE_*. |
||
| 1537 | * |
||
| 1538 | * INFO: used for "fetch()" and "fetchAll()" |
||
| 1539 | * |
||
| 1540 | * @param string $default_result_type |
||
| 1541 | * |
||
| 1542 | * @return void |
||
| 1543 | */ |
||
| 1544 | 3 | public function setDefaultResultType(string $default_result_type = self::RESULT_TYPE_OBJECT) |
|
| 1558 | |||
| 1559 | /** |
||
| 1560 | * @param int $offset |
||
| 1561 | * @param int|null $length |
||
| 1562 | * @param bool $preserve_keys |
||
| 1563 | * |
||
| 1564 | * @return array |
||
| 1565 | */ |
||
| 1566 | 1 | public function &slice( |
|
| 1595 | } |
||
| 1596 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the interface: