handle = $handle; if (is_object($this->handle)) { $this->columns = $this->handle->fetch_fields(); } } public function __destruct() { if (is_object($this->handle)) { $this->handle->free(); } } public function getIterator(): Traversable { $floatTypes = [MYSQLI_TYPE_FLOAT, MYSQLI_TYPE_DOUBLE, MYSQLI_TYPE_DECIMAL, MYSQLI_TYPE_NEWDECIMAL]; if (is_object($this->handle)) { while ($row = $this->handle->fetch_array(MYSQLI_NUM)) { $data = []; foreach ($row as $i => $value) { if (!isset($this->columns[$i])) { throw new DatabaseException("Can't get metadata for column $i"); } if (in_array($this->columns[$i]->type, $floatTypes ?? [])) { $value = (float)$value; } $data[$this->columns[$i]->name] = $value; } yield $data; } // Check for the method first since $this->handle is a mixed type if (method_exists($this->handle, 'data_seek')) { // Reset so the query can be iterated over again $this->handle->data_seek(0); } } } public function numRecords() { if (is_object($this->handle)) { return $this->handle->num_rows; } return null; } }