Context
Found while working phpdb-mysql#60 (mago analyze fixes).
Problem
DriverInterface::createResult($resource), DriverInterface::createStatement($sqlOrResource), and StatementInterface::getResource() are documented with a generic resource docblock type, intended to stay valid across every supported RDBMS platform. Concrete per-platform implementations (e.g. phpdb-mysql) pass/return real objects (mysqli, mysqli_result, mysqli_stmt), not resource handles, since mysqli has been object-oriented since its introduction in PHP 5.0 and was never part of PHP's resource-to-object migration. Static analyzers (mago, phpstan, psalm) flag every concrete usage as a type mismatch against the generic resource docblock, requiring local suppressions in every downstream platform package.
Proposed direction
Use PHP docblock generics (@template) on the interfaces instead of a fixed resource type, so the interface stays a single, platform-agnostic contract, and each concrete implementation narrows the generic to its own real type via @implements:
/** @template TResource */
interface DriverInterface
{
/** @param TResource $resource */
public function createResult($resource): ResultInterface;
}
/** @implements DriverInterface<mysqli|mysqli_result|mysqli_stmt> */
final class Driver implements DriverInterface { /* ... */ }
This avoids introducing per-RDBMS interfaces (a platform still free to use literal resource handles, e.g. a hypothetical oci8 implementation, can declare DriverInterface<resource>), while letting static analyzers correctly understand each concrete implementation's real type without suppressions. Same pattern applies to StatementInterface::getResource() and DriverInterface::createStatement()'s $sqlOrResource parameter.
Context
Found while working phpdb-mysql#60 (mago analyze fixes).
Problem
DriverInterface::createResult($resource),DriverInterface::createStatement($sqlOrResource), andStatementInterface::getResource()are documented with a genericresourcedocblock type, intended to stay valid across every supported RDBMS platform. Concrete per-platform implementations (e.g. phpdb-mysql) pass/return real objects (mysqli,mysqli_result,mysqli_stmt), notresourcehandles, since mysqli has been object-oriented since its introduction in PHP 5.0 and was never part of PHP's resource-to-object migration. Static analyzers (mago, phpstan, psalm) flag every concrete usage as a type mismatch against the genericresourcedocblock, requiring local suppressions in every downstream platform package.Proposed direction
Use PHP docblock generics (
@template) on the interfaces instead of a fixedresourcetype, so the interface stays a single, platform-agnostic contract, and each concrete implementation narrows the generic to its own real type via@implements:This avoids introducing per-RDBMS interfaces (a platform still free to use literal
resourcehandles, e.g. a hypothetical oci8 implementation, can declareDriverInterface<resource>), while letting static analyzers correctly understand each concrete implementation's real type without suppressions. Same pattern applies toStatementInterface::getResource()andDriverInterface::createStatement()'s$sqlOrResourceparameter.