Skip to content

Conversation

@simon-mundy
Copy link
Collaborator

@simon-mundy simon-mundy commented Jan 9, 2026

Q A
Documentation no
Bugfix yes
BC Break yes
New Feature no
RFC no
QA yes
House Keeping yes

Description

Adds PHP8.2+ modernisation, strong typing and general code cleanup.
Adds new RowPrototypeInterface to solve issues with new ResultSet and RowGateway
Adds 100% code coverage testing

Closes #63

  Refactor RowGateway and TableGateway classes to use PHP 8+ features:

  - Replace docblock type hints with native property type declarations using union types and nullable types
  - Add return type declarations to methods (offsetExists(): bool, offsetGet(): mixed, count(): int, etc.)
  - Use static return type for fluent interface methods
  - Convert constructor parameters to use union types in RowGateway and TableGateway

  Improve type safety and code quality:
  - Replace loose equality (==) with strict equality (===) in primary key comparisons
  - Simplify initialization checks using null comparisons instead of instanceof checks
  - Add proper instanceof StatementInterface guards before executing statements
  - Add lazy initialization to getFeatureSet(), getResultSetPrototype(), and getSql() getters
  - Add default case to match expression in TableGateway constructor
  - Update TableGatewayInterface::getTable() to return proper union type

  Cleanup:
  - Remove unused imports (is_string)
  - Remove redundant comments and phpcs ignore directives
  - Remove unused $alias variable in foreach loop
  - Fix @todo annotation format

  Update tests:
  - Change primaryKeyColumn to array format to match expected type
  - Remove unnecessary setAccessible(true) calls (not needed in PHP 8.1+)

Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Reverted constructor in TableGateway to allow nullable args and pass existing tests

Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Signed-off-by: Simon Mundy <simon.mundy@peptolab.com>
Introduced spread operators instead of call_user_func_array
Modified existing files to add RowPrototypeInterface
Updated tests
@simon-mundy simon-mundy added this to the 0.6.0 milestone Jan 9, 2026
@simon-mundy simon-mundy self-assigned this Jan 9, 2026
@simon-mundy simon-mundy added bug Something isn't working enhancement New feature or request qa Improvements in quality assurance of the project Lang Feature Refactor Refactoring to new language features labels Jan 9, 2026
@github-project-automation github-project-automation bot moved this to Todo in @phpdb Jan 9, 2026
/**
* Exchange the current data for the provided array.
*/
public function exchangeArray(array $array): mixed;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This return type needs to array instead of mixed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it doesn't - this could return any number of different objects depending on implementation. See AbstractRowGateway

* Set the row object prototype
*/
abstract public function setRowPrototype(ArrayObject $rowPrototype): ResultSetInterface;
abstract public function setRowPrototype(ArrayObject|RowPrototypeInterface $rowPrototype): ResultSetInterface;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither the getter nor setter methods are needed as abstract methods here since they are both in the interface.

The return type for the getter needs narrowed to ArrayObject|RowPrototypeInterface since if a custom prototype is not set then a default ArrayObject instance will be created.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That creates a problem with PhpDb\ResultSet\HydratingResultSet::getRowPrototype


/** @phpstan-ignore instanceof.alwaysTrue */
if (! $this->featureSet instanceof Feature\FeatureSet) {
if ($this->featureSet === null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still of the mindset that this can be simplified. The entire method body.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For discussion - weighing up refactoring vs breaking change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request Lang Feature Refactor Refactoring to new language features qa Improvements in quality assurance of the project

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

[RFC]: Refactor Typing in \TableGateway

3 participants