From 9e4c73068b3727a92bac33d9002bc42e96d349b6 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Mon, 1 Dec 2025 09:32:19 +0100 Subject: [PATCH 1/4] Mark parameters that default to null as nullable to ensure 8.4 compatibilty Since PHP 8.4 implicitly nullable parameters are deprecated. --- src/Connection.php | 30 +++++++++++++++--------------- src/Expression.php | 4 ++-- src/QueryBuilder.php | 36 ++++++++++++++++++------------------ src/Test/SqlAssertions.php | 2 +- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Connection.php b/src/Connection.php index 9480fe7..5c29713 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -210,11 +210,11 @@ public function ping($reconnect = true) * Fetch and return all result rows as sequential array * * @param Select|string $stmt The SQL statement to prepare and execute. - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * * @return array */ - public function fetchAll($stmt, array $values = null) + public function fetchAll($stmt, ?array $values = null) { return $this->prepexec($stmt, $values) ->fetchAll(); @@ -224,11 +224,11 @@ public function fetchAll($stmt, array $values = null) * Fetch and return the first column of all result rows as sequential array * * @param Select|string $stmt The SQL statement to prepare and execute. - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * * @return array */ - public function fetchCol($stmt, array $values = null) + public function fetchCol($stmt, ?array $values = null) { return $this->prepexec($stmt, $values) ->fetchAll(PDO::FETCH_COLUMN, 0); @@ -238,11 +238,11 @@ public function fetchCol($stmt, array $values = null) * Fetch and return the first row of the result rows * * @param Select|string $stmt The SQL statement to prepare and execute. - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * * @return array */ - public function fetchOne($stmt, array $values = null) + public function fetchOne($stmt, ?array $values = null) { return $this->prepexec($stmt, $values) ->fetch(); @@ -251,7 +251,7 @@ public function fetchOne($stmt, array $values = null) /** * Alias of {@link fetchOne()} */ - public function fetchRow($stmt, array $values = null) + public function fetchRow($stmt, ?array $values = null) { return $this->prepexec($stmt, $values) ->fetch(); @@ -263,11 +263,11 @@ public function fetchRow($stmt, array $values = null) * First column is the key and the second column is the value. * * @param Select|string $stmt The SQL statement to prepare and execute. - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * * @return array */ - public function fetchPairs($stmt, array $values = null) + public function fetchPairs($stmt, ?array $values = null) { return $this->prepexec($stmt, $values) ->fetchAll(PDO::FETCH_KEY_PAIR); @@ -277,11 +277,11 @@ public function fetchPairs($stmt, array $values = null) * Fetch and return the first column of the first result row * * @param Select|string $stmt The SQL statement to prepare and execute. - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * * @return string */ - public function fetchScalar($stmt, array $values = null) + public function fetchScalar($stmt, ?array $values = null) { return $this->prepexec($stmt, $values) ->fetchColumn(0); @@ -343,11 +343,11 @@ public function yieldAll($stmt, ...$args) * Yield the first column of each result row * * @param Select|string $stmt The SQL statement to prepare and execute - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * * @return \Generator */ - public function yieldCol($stmt, array $values = null) + public function yieldCol($stmt, ?array $values = null) { $sth = $this->prepexec($stmt, $values); @@ -362,11 +362,11 @@ public function yieldCol($stmt, array $values = null) * Yield key-value pairs with the first column as key and the second column as value for each result row * * @param Select|string $stmt The SQL statement to prepare and execute - * @param array $values Values to bind to the statement + * @param ?array $values Values to bind to the statement * * @return \Generator */ - public function yieldPairs($stmt, array $values = null) + public function yieldPairs($stmt, ?array $values = null) { $sth = $this->prepexec($stmt, $values); diff --git a/src/Expression.php b/src/Expression.php index 83c10bd..0f544b1 100644 --- a/src/Expression.php +++ b/src/Expression.php @@ -20,10 +20,10 @@ class Expression implements ExpressionInterface * Create a new database expression * * @param string $statement The statement of the expression - * @param array $columns The columns used by the expression + * @param ?array $columns The columns used by the expression * @param mixed ...$values The values for the expression */ - public function __construct($statement, array $columns = null, ...$values) + public function __construct($statement, ?array $columns = null, ...$values) { $this->statement = $statement; $this->columns = $columns; diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index 07b5e3e..f65c68c 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -360,11 +360,11 @@ public function buildWith(array $with, array &$values) /** * Build the DELETE FROM part of a query * - * @param array $from + * @param ?array $from * * @return string The DELETE FROM part of a query */ - public function buildDeleteFrom(array $from = null) + public function buildDeleteFrom(?array $from = null) { if ($from === null) { return ''; @@ -486,12 +486,12 @@ public function buildCondition(array $condition, array &$values) /** * Build the WHERE part of a query * - * @param array $where + * @param ?array $where * @oaram array $values * * @return string The WHERE part of the query */ - public function buildWhere(array $where = null, array &$values = []) + public function buildWhere(?array $where = null, array &$values = []) { if ($where === null) { return ''; @@ -609,12 +609,12 @@ public function buildSelect(array $columns, $distinct, array &$values) /** * Build the FROM part of a query * - * @param array $from + * @param ?array $from * @param array $values * * @return string The FROM part of the query */ - public function buildFrom(array $from = null, array &$values = []) + public function buildFrom(?array $from = null, array &$values = []) { if ($from === null) { return ''; @@ -686,12 +686,12 @@ public function buildJoin($joins, array &$values) /** * Build the GROUP BY part of a query * - * @param array $groupBy + * @param ?array $groupBy * @param array $values * * @return string The GROUP BY part of the query */ - public function buildGroupBy(array $groupBy = null, array &$values = []) + public function buildGroupBy(?array $groupBy = null, array &$values = []) { if ($groupBy === null) { return ''; @@ -711,12 +711,12 @@ public function buildGroupBy(array $groupBy = null, array &$values = []) /** * Build the HAVING part of a query * - * @param array $having + * @param ?array $having * @param array $values * * @return string The HAVING part of the query */ - public function buildHaving(array $having = null, array &$values = []) + public function buildHaving(?array $having = null, array &$values = []) { if ($having === null) { return ''; @@ -728,12 +728,12 @@ public function buildHaving(array $having = null, array &$values = []) /** * Build the ORDER BY part of a query * - * @param array $orderBy + * @param ?array $orderBy * @param array $values * * @return string The ORDER BY part of the query */ - public function buildOrderBy(array $orderBy = null, array &$values = []) + public function buildOrderBy(?array $orderBy = null, array &$values = []) { if ($orderBy === null) { return ''; @@ -798,12 +798,12 @@ public function buildLimitOffset($limit = null, $offset = null) /** * Build the UNION parts of a query * - * @param array $unions + * @param ?array $unions * @param array $values * * @return array|null The UNION parts of the query */ - public function buildUnions(array $unions = null, array &$values = []) + public function buildUnions(?array $unions = null, array &$values = []) { if ($unions === null) { return null; @@ -829,11 +829,11 @@ public function buildUnions(array $unions = null, array &$values = []) /** * Build the UPDATE {table} part of a query * - * @param array $updateTable The table to UPDATE + * @param ?array $updateTable The table to UPDATE * * @return string The UPDATE {table} part of the query */ - public function buildUpdateTable(array $updateTable = null) + public function buildUpdateTable(?array $updateTable = null) { if ($updateTable === null) { return ''; @@ -857,12 +857,12 @@ public function buildUpdateTable(array $updateTable = null) /** * Build the SET part of a UPDATE query * - * @param array $set + * @param ?array $set * @param array $values * * @return string The SET part of a UPDATE query */ - public function buildUpdateSet(array $set = null, array &$values = []) + public function buildUpdateSet(?array $set = null, array &$values = []) { if (empty($set)) { return ''; diff --git a/src/Test/SqlAssertions.php b/src/Test/SqlAssertions.php index 74a04ba..62d4ab0 100644 --- a/src/Test/SqlAssertions.php +++ b/src/Test/SqlAssertions.php @@ -33,7 +33,7 @@ protected function setUpSqlAssertions(): void * * @return void */ - public function assertSql(string $sql, $statement, array $values = null, string $message = ''): void + public function assertSql(string $sql, $statement, ?array $values = null, string $message = ''): void { // Reduce whitespaces to just one space $sql = preg_replace('/\s+/', ' ', trim($sql)); From 8520935b21bda8bf28437ea9c6c475781b7ac272 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Mon, 1 Dec 2025 10:25:48 +0100 Subject: [PATCH 2/4] Use PDO constants adequate for the running PHP version Since PHP 8.5 driver-specific PDO constants are deprecated, their replacements are only available since PHP 8.4. --- src/Adapter/Mysql.php | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Adapter/Mysql.php b/src/Adapter/Mysql.php index 2421cae..7146579 100644 --- a/src/Adapter/Mysql.php +++ b/src/Adapter/Mysql.php @@ -22,33 +22,40 @@ public function setClientTimezone(Connection $db) public function getOptions(Config $config) { $options = parent::getOptions($config); + // In PHP 8.5+, driver-specific constants of the PDO class are deprecated, + // but the replacements are only available since php 8.4 + if (version_compare(PHP_VERSION, '8.4.0', '<')) { + $mysqlConstantPrefix = 'PDO::MYSQL_ATTR_'; + } else { + $mysqlConstantPrefix = 'Pdo\Mysql::ATTR_'; + } if (! empty($config->useSsl)) { if (! empty($config->sslKey)) { - $options[PDO::MYSQL_ATTR_SSL_KEY] = $config->sslKey; + $options[constant($mysqlConstantPrefix . 'SSL_KEY')] = $config->sslKey; } if (! empty($config->sslCert)) { - $options[PDO::MYSQL_ATTR_SSL_CERT] = $config->sslCert; + $options[constant($mysqlConstantPrefix . 'SSL_CERT')] = $config->sslCert; } if (! empty($config->sslCa)) { - $options[PDO::MYSQL_ATTR_SSL_CA] = $config->sslCa; + $options[constant($mysqlConstantPrefix . 'SSL_CA')] = $config->sslCa; } if (! empty($config->sslCapath)) { - $options[PDO::MYSQL_ATTR_SSL_CAPATH] = $config->sslCapath; + $options[constant($mysqlConstantPrefix . 'SSL_CAPATH')] = $config->sslCapath; } if (! empty($config->sslCipher)) { - $options[PDO::MYSQL_ATTR_SSL_CIPHER] = $config->sslCipher; + $options[constant($mysqlConstantPrefix . 'SSL_CIPHER')] = $config->sslCipher; } if ( - defined('PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT') + defined($mysqlConstantPrefix . 'SSL_VERIFY_SERVER_CERT') && ! empty($config->sslDoNotVerifyServerCert) ) { - $options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false; + $options[constant($mysqlConstantPrefix . 'SSL_VERIFY_SERVER_CERT')] = false; } } From 7db51db57b4c6df4f62dfa4790d723f707c631ee Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Wed, 10 Dec 2025 13:52:19 +0100 Subject: [PATCH 3/4] phpstan.neon: Remove now superfluous scanDirectories `scanDirectories` was set to `/usr/share/icinga-php` to simplify local testing, as both the Icinga PHP Library and Icinga PHP Thirdparty are installed there in our development environment. Our individual PHP library components, which make up these libraries, are self-contained, as they define all necessary dependencies themselves. This then requires testing with exactly these dependencies instead of an arbitrary folder that could contain anything, e.g., dependencies in unexpected versions or dependencies that have not yet been defined. For remote and local testing, `composer install` must be executed and tests must be performed with exactly the resulting dependencies. Since PHPStan uses the Composer autoloader by default, if available, `scanDirectories` does not need to be defined at all. --- phpstan.neon | 3 --- 1 file changed, 3 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index f58b54c..5ee24f4 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -11,9 +11,6 @@ parameters: paths: - src - scanDirectories: - - vendor - universalObjectCratesClasses: # to ignore magic property errors - ipl\Sql\Config From 9aaf2fd7340522153256537e8b6a106e7f5f547c Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Thu, 11 Dec 2025 08:59:24 +0100 Subject: [PATCH 4/4] TestConnection: make setFetchMode declaration compatible with parent class `PDOStatement::setFetchmode()` takes variable-length argument list as second parameter. One of the extended local classed inside TestConnection did not match this siganture. --- src/Test/TestConnection.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Test/TestConnection.php b/src/Test/TestConnection.php index 913070f..11d0117 100644 --- a/src/Test/TestConnection.php +++ b/src/Test/TestConnection.php @@ -43,7 +43,7 @@ public function getIterator(): \Iterator return new \ArrayIterator([]); } - public function setFetchMode($mode, ...$args): bool + public function setFetchMode($mode, ...$args): true { return true; } @@ -55,7 +55,7 @@ public function getIterator(): \Iterator return new \ArrayIterator([]); } - public function setFetchMode($mode, $params = null): bool + public function setFetchMode($mode, ...$params): true { return true; }