From abd601d34f58f9cd310a2b5ce1d4f2b4ce2c2be1 Mon Sep 17 00:00:00 2001 From: Johannes Rauh Date: Wed, 10 Dec 2025 07:28:47 +0100 Subject: [PATCH 01/11] Remove build status from readme --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index d1efc1e..97cb699 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Icinga PHP Library - SQL abstraction layer -![Build Status](https://github.com/Icinga/ipl-sql/workflows/PHP%20Tests/badge.svg?branch=main) - The package `ipl\Sql` provides a [database connection abstraction](#sql-connection) and an [SQL query abstraction layer](#sql-queries) for building SQL queries via an OOP API. From 315a810f89a999c3db30acedfd1142edf6a4ce68 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Mon, 1 Dec 2025 09:32:19 +0100 Subject: [PATCH 02/11] Mark parameters that default to null as nullable to ensure 8.4 compatibilty --- 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 87511930d54e8d0ae93ea0feb81c2924aca9c215 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Mon, 1 Dec 2025 10:25:48 +0100 Subject: [PATCH 03/11] Replace PDO constants, that are deprecated in PHP 8.5 with their replacements, if they are available for the current PHP version --- 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..4249f06 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.5.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 e6e35a99e6579c7771eedeec671f83c98e34a60b Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Wed, 3 Dec 2025 08:03:53 +0100 Subject: [PATCH 04/11] Adjust version threshold for new Mysql constants from 8.5 to 8.4 --- src/Adapter/Mysql.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Adapter/Mysql.php b/src/Adapter/Mysql.php index 4249f06..7146579 100644 --- a/src/Adapter/Mysql.php +++ b/src/Adapter/Mysql.php @@ -24,7 +24,7 @@ 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.5.0', '<')) { + if (version_compare(PHP_VERSION, '8.4.0', '<')) { $mysqlConstantPrefix = 'PDO::MYSQL_ATTR_'; } else { $mysqlConstantPrefix = 'Pdo\Mysql::ATTR_'; From 8492d69a2e797f43822fcf779a2cbebc33adb427 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Wed, 10 Dec 2025 13:52:19 +0100 Subject: [PATCH 05/11] 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. - https://github.com/Icinga/ipl-sql/pull/93 makes it superfluous for github actions --- 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 be685ede8e960f450d43eb5ed2e8327b23acd216 Mon Sep 17 00:00:00 2001 From: Bastian Lederer Date: Thu, 11 Dec 2025 08:59:24 +0100 Subject: [PATCH 06/11] TestConnection: make setFetchMode declaration compatible with parent class --- 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; } From d1a3739b9797b74b47cceda90da8b667de26ec77 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Tue, 9 Dec 2025 09:17:19 +0100 Subject: [PATCH 07/11] Add property, parameter and return types - Use [] instead of list() --- src/Adapter/BaseAdapter.php | 18 ++-- src/Adapter/Mssql.php | 8 +- src/Adapter/Mysql.php | 9 +- src/Adapter/Oracle.php | 4 +- src/Adapter/Pgsql.php | 2 +- src/Adapter/Sqlite.php | 2 +- src/CommonTableExpression.php | 10 +- src/CommonTableExpressionInterface.php | 6 +- src/Compat/FilterProcessor.php | 4 +- src/Config.php | 45 ++++----- src/Connection.php | 121 +++++++++++++------------ src/Contract/Adapter.php | 8 +- src/Contract/Quoter.php | 2 +- src/Cursor.php | 24 ++--- src/Delete.php | 12 +-- src/Expression.php | 18 ++-- src/ExpressionInterface.php | 8 +- src/Filter/In.php | 2 +- src/Filter/InAndNotInUtils.php | 6 +- src/Filter/NotIn.php | 2 +- src/Insert.php | 34 +++---- src/LimitOffset.php | 42 +++------ src/LimitOffsetInterface.php | 24 ++--- src/OrderBy.php | 12 +-- src/OrderByInterface.php | 14 +-- src/QueryBuilder.php | 77 ++++++++-------- src/Select.php | 92 +++++++++---------- src/Sql.php | 8 +- src/Test/TestConnection.php | 12 ++- src/Update.php | 22 ++--- src/Where.php | 34 +++---- src/WhereInterface.php | 14 +-- 32 files changed, 341 insertions(+), 355 deletions(-) diff --git a/src/Adapter/BaseAdapter.php b/src/Adapter/BaseAdapter.php index f062f63..29994f3 100644 --- a/src/Adapter/BaseAdapter.php +++ b/src/Adapter/BaseAdapter.php @@ -21,13 +21,13 @@ abstract class BaseAdapter implements Adapter * * @var array */ - protected $quoteCharacter = ['"', '"']; + protected array $quoteCharacter = ['"', '"']; /** @var string Character to use for escaping quote characters */ - protected $escapeCharacter = '\\"'; + protected string $escapeCharacter = '\\"'; /** @var array Default PDO connect options */ - protected $options = [ + protected array $options = [ PDO::ATTR_CASE => PDO::CASE_NATURAL, PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, @@ -35,7 +35,7 @@ abstract class BaseAdapter implements Adapter PDO::ATTR_STRINGIFY_FETCHES => false ]; - public function getDsn(Config $config) + public function getDsn(Config $config): string { $dsn = "{$config->db}:"; @@ -50,7 +50,7 @@ public function getDsn(Config $config) return $dsn . implode(';', $parts); } - public function getOptions(Config $config) + public function getOptions(Config $config): array { if (is_array($config->options)) { return $config->options + $this->options; @@ -59,12 +59,12 @@ public function getOptions(Config $config) return $this->options; } - public function setClientTimezone(Connection $db) + public function setClientTimezone(Connection $db): static { return $this; } - public function quoteIdentifier($identifiers) + public function quoteIdentifier(array|string $identifiers): string { if (is_string($identifiers)) { $identifiers = explode('.', $identifiers); @@ -83,7 +83,7 @@ public function quoteIdentifier($identifiers) return implode('.', $identifiers); } - public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder) + public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder): static { $queryBuilder->on(QueryBuilder::ON_ASSEMBLE_SELECT, function (Select $select): void { if ($select->hasOrderBy()) { @@ -105,7 +105,7 @@ public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder) return $this; } - protected function getTimezoneOffset() + protected function getTimezoneOffset(): string { $tz = new DateTimeZone(date_default_timezone_get()); $offset = $tz->getOffset(new DateTime()); diff --git a/src/Adapter/Mssql.php b/src/Adapter/Mssql.php index c9f11ce..55d6c95 100644 --- a/src/Adapter/Mssql.php +++ b/src/Adapter/Mssql.php @@ -10,11 +10,11 @@ class Mssql extends BaseAdapter { - protected $quoteCharacter = ['[', ']']; + protected array $quoteCharacter = ['[', ']']; - protected $escapeCharacter = '[[]'; + protected string $escapeCharacter = '[[]'; - public function getDsn(Config $config) + public function getDsn(Config $config): string { $drivers = array_intersect(['sqlsrv', 'dblib', 'mssql', 'sybase'], PDO::getAvailableDrivers()); @@ -62,7 +62,7 @@ public function getDsn(Config $config) return $dsn; } - public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder) + public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder): static { parent::registerQueryBuilderCallbacks($queryBuilder); diff --git a/src/Adapter/Mysql.php b/src/Adapter/Mysql.php index 7146579..19683b3 100644 --- a/src/Adapter/Mysql.php +++ b/src/Adapter/Mysql.php @@ -4,22 +4,21 @@ use ipl\Sql\Config; use ipl\Sql\Connection; -use PDO; class Mysql extends BaseAdapter { - protected $quoteCharacter = ['`', '`']; + protected array $quoteCharacter = ['`', '`']; - protected $escapeCharacter = '``'; + protected string $escapeCharacter = '``'; - public function setClientTimezone(Connection $db) + public function setClientTimezone(Connection $db): static { $db->exec('SET time_zone = ' . $db->quote($this->getTimezoneOffset())); return $this; } - public function getOptions(Config $config) + public function getOptions(Config $config): array { $options = parent::getOptions($config); // In PHP 8.5+, driver-specific constants of the PDO class are deprecated, diff --git a/src/Adapter/Oracle.php b/src/Adapter/Oracle.php index de0aee5..a6c5aa0 100644 --- a/src/Adapter/Oracle.php +++ b/src/Adapter/Oracle.php @@ -7,7 +7,7 @@ class Oracle extends BaseAdapter { - public function getDsn(Config $config) + public function getDsn(Config $config): string { $dsn = 'oci:dbname='; @@ -30,7 +30,7 @@ public function getDsn(Config $config) return $dsn; } - public function setClientTimezone(Connection $db) + public function setClientTimezone(Connection $db): static { $db->prepexec('ALTER SESSION SET TIME_ZONE = ?', [$this->getTimezoneOffset()]); diff --git a/src/Adapter/Pgsql.php b/src/Adapter/Pgsql.php index 18bf15d..871d059 100644 --- a/src/Adapter/Pgsql.php +++ b/src/Adapter/Pgsql.php @@ -6,7 +6,7 @@ class Pgsql extends BaseAdapter { - public function setClientTimezone(Connection $db) + public function setClientTimezone(Connection $db): static { $db->exec(sprintf('SET TIME ZONE INTERVAL %s HOUR TO MINUTE', $db->quote($this->getTimezoneOffset()))); diff --git a/src/Adapter/Sqlite.php b/src/Adapter/Sqlite.php index 9f4e209..e040b6f 100644 --- a/src/Adapter/Sqlite.php +++ b/src/Adapter/Sqlite.php @@ -6,7 +6,7 @@ class Sqlite extends BaseAdapter { - public function getDsn(Config $config) + public function getDsn(Config $config): string { return "sqlite:{$config->dbname}"; } diff --git a/src/CommonTableExpression.php b/src/CommonTableExpression.php index 596ec39..5877fbf 100644 --- a/src/CommonTableExpression.php +++ b/src/CommonTableExpression.php @@ -17,21 +17,21 @@ trait CommonTableExpression * * @var array[] */ - protected $with = []; + protected array $with = []; - public function getWith() + public function getWith(): array { return $this->with; } - public function with(Select $query, $alias, $recursive = false) + public function with(Select $query, string $alias, bool $recursive = false): static { $this->with[] = [$query, $alias, $recursive]; return $this; } - public function resetWith() + public function resetWith(): static { $this->with = []; @@ -43,7 +43,7 @@ public function resetWith() * * Shall be called by using classes in their __clone() */ - protected function cloneCte() + protected function cloneCte(): void { foreach ($this->with as &$cte) { $cte[0] = clone $cte[0]; diff --git a/src/CommonTableExpressionInterface.php b/src/CommonTableExpressionInterface.php index 7e93bc8..9a528bd 100644 --- a/src/CommonTableExpressionInterface.php +++ b/src/CommonTableExpressionInterface.php @@ -17,7 +17,7 @@ interface CommonTableExpressionInterface * * @return array[] */ - public function getWith(); + public function getWith(): array; /** * Add a CTE @@ -28,12 +28,12 @@ public function getWith(); * * @return $this */ - public function with(Select $query, $alias, $recursive = false); + public function with(Select $query, string $alias, bool $recursive = false): static; /** * Reset all CTEs * * @return $this */ - public function resetWith(); + public function resetWith(): static; } diff --git a/src/Compat/FilterProcessor.php b/src/Compat/FilterProcessor.php index 1ed1c3d..457b712 100644 --- a/src/Compat/FilterProcessor.php +++ b/src/Compat/FilterProcessor.php @@ -13,7 +13,7 @@ class FilterProcessor { - public static function assembleFilter(Filter\Rule $filter, $level = 0) + public static function assembleFilter(Filter\Rule $filter, int $level = 0): ?array { $condition = null; @@ -60,7 +60,7 @@ public static function assembleFilter(Filter\Rule $filter, $level = 0) return $condition; } - public static function assemblePredicate(Filter\Condition $filter) + public static function assemblePredicate(Filter\Condition $filter): array { $column = $filter->getColumn(); $expression = $filter->getValue(); diff --git a/src/Config.php b/src/Config.php index 5fa103e..e4fdb49 100644 --- a/src/Config.php +++ b/src/Config.php @@ -2,34 +2,31 @@ namespace ipl\Sql; -use InvalidArgumentException; use ipl\Stdlib\Str; use OutOfRangeException; -use function ipl\Stdlib\get_php_type; - /** * SQL connection configuration */ class Config { - /** @var string Type of the DBMS */ - public $db; + /** @var ?string Type of the DBMS */ + public ?string $db = null; - /** @var string Database host */ - public $host; + /** @var ?string Database host */ + public ?string $host = null; - /** @var int Database port */ - public $port; + /** @var string|int|null Database port */ + public string|int|null $port = null; - /** @var string Database name */ - public $dbname; + /** @var ?string Database name */ + public ?string $dbname = null; - /** @var string Username to use for authentication */ - public $username; + /** @var ?string Username to use for authentication */ + public ?string $username = null; - /** @var string Password to use for authentication */ - public $password; + /** @var ?string Password to use for authentication */ + public ?string $password = null; /** * Character set for the connection @@ -38,7 +35,7 @@ class Config * * @var string */ - public $charset; + public string $charset = ''; /** * PDO connect options @@ -48,10 +45,10 @@ class Config * * @var array */ - public $options; + public array $options = []; /** @var array Extra settings e.g. for SQL SSL connections */ - protected $extraSettings = []; + protected array $extraSettings = []; /** * Create a new SQL connection configuration from the given configuration key-value pairs @@ -59,19 +56,9 @@ class Config * Keys will be converted to camelCase, e.g. use_ssl → useSsl. * * @param iterable $config Configuration key-value pairs - * - * @throws InvalidArgumentException If $config is not iterable */ - public function __construct($config) + public function __construct(iterable $config) { - if (! is_iterable($config)) { - throw new InvalidArgumentException(sprintf( - '%s expects parameter one to be iterable, got %s instead', - __METHOD__, - get_php_type($config) - )); - } - foreach ($config as $key => $value) { $key = Str::camel($key); $this->$key = $value; diff --git a/src/Connection.php b/src/Connection.php index 5c29713..40b41d3 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -4,6 +4,7 @@ use BadMethodCallException; use Exception; +use Generator; use InvalidArgumentException; use ipl\Sql\Contract\Adapter; use ipl\Sql\Contract\Quoter; @@ -11,6 +12,7 @@ use LogicException; use PDO; use PDOStatement; +use Throwable; /** * Connection to a SQL database using the native PDO for database access @@ -20,27 +22,27 @@ class Connection implements Quoter use Plugins; /** @var Config */ - protected $config; + protected Config $config; /** @var ?PDO */ - protected $pdo; + protected ?PDO $pdo = null; - /** @var QueryBuilder */ - protected $queryBuilder; + /** @var ?QueryBuilder */ + protected ?QueryBuilder $queryBuilder = null; /** @var Adapter */ - protected $adapter; + protected Adapter $adapter; /** * Create a new database connection using the given config for initialising the options for the connection * * {@link init()} is called after construction. * - * @param Config|iterable $config + * @param iterable|Config $config * * @throws InvalidArgumentException If there's no adapter for the given database available */ - public function __construct($config) + public function __construct(iterable|Config $config) { $config = $config instanceof Config ? $config : new Config($config); @@ -69,7 +71,7 @@ public function __construct($config) * @throws BadMethodCallException If the called method does not exist * */ - public function __call($name, array $arguments) + public function __call(string $name, array $arguments) { $this->connect(); @@ -88,7 +90,7 @@ public function __call($name, array $arguments) * * If you have to adjust the connection after construction, override this method. */ - public function init() + public function init(): void { } @@ -97,7 +99,7 @@ public function init() * * @return Adapter */ - public function getAdapter() + public function getAdapter(): Adapter { return $this->adapter; } @@ -107,7 +109,7 @@ public function getAdapter() * * @return Config */ - public function getConfig() + public function getConfig(): Config { return $this->config; } @@ -117,7 +119,7 @@ public function getConfig() * * @return QueryBuilder */ - public function getQueryBuilder() + public function getQueryBuilder(): QueryBuilder { if ($this->queryBuilder === null) { $this->queryBuilder = new QueryBuilder($this->adapter); @@ -134,7 +136,7 @@ public function getQueryBuilder() * * @return PDO */ - protected function createPdoAdapter() + protected function createPdoAdapter(): PDO { $adapter = $this->getAdapter(); @@ -153,7 +155,7 @@ protected function createPdoAdapter() * * @return $this */ - public function connect() + public function connect(): static { if ($this->pdo !== null) { return $this; @@ -175,7 +177,7 @@ public function connect() * * @return $this */ - public function disconnect() + public function disconnect(): static { $this->pdo = null; @@ -189,11 +191,11 @@ public function disconnect() * * @return bool */ - public function ping($reconnect = true) + public function ping(bool $reconnect = true): bool { try { $this->query('SELECT 1')->closeCursor(); - } catch (Exception $e) { + } catch (Throwable) { if (! $reconnect) { return false; } @@ -214,7 +216,7 @@ public function ping($reconnect = true) * * @return array */ - public function fetchAll($stmt, ?array $values = null) + public function fetchAll(Select|string $stmt, ?array $values = null): array { return $this->prepexec($stmt, $values) ->fetchAll(); @@ -228,7 +230,7 @@ public function fetchAll($stmt, ?array $values = null) * * @return array */ - public function fetchCol($stmt, ?array $values = null) + public function fetchCol(Select|string $stmt, ?array $values = null): array { return $this->prepexec($stmt, $values) ->fetchAll(PDO::FETCH_COLUMN, 0); @@ -240,9 +242,9 @@ public function fetchCol($stmt, ?array $values = null) * @param Select|string $stmt The SQL statement to prepare and execute. * @param ?array $values Values to bind to the statement * - * @return array + * @return mixed */ - public function fetchOne($stmt, ?array $values = null) + public function fetchOne(Select|string $stmt, ?array $values = null): mixed { return $this->prepexec($stmt, $values) ->fetch(); @@ -251,7 +253,7 @@ public function fetchOne($stmt, ?array $values = null) /** * Alias of {@link fetchOne()} */ - public function fetchRow($stmt, ?array $values = null) + public function fetchRow(Select|string $stmt, ?array $values = null): mixed { return $this->prepexec($stmt, $values) ->fetch(); @@ -267,7 +269,7 @@ public function fetchRow($stmt, ?array $values = null) * * @return array */ - public function fetchPairs($stmt, ?array $values = null) + public function fetchPairs(Select|string $stmt, ?array $values = null): array { return $this->prepexec($stmt, $values) ->fetchAll(PDO::FETCH_KEY_PAIR); @@ -279,9 +281,9 @@ public function fetchPairs($stmt, ?array $values = null) * @param Select|string $stmt The SQL statement to prepare and execute. * @param ?array $values Values to bind to the statement * - * @return string + * @return mixed */ - public function fetchScalar($stmt, ?array $values = null) + public function fetchScalar(Select|string $stmt, ?array $values = null): mixed { return $this->prepexec($stmt, $values) ->fetchColumn(0); @@ -295,9 +297,9 @@ public function fetchScalar($stmt, ?array $values = null) * @param Select|string $stmt The SQL statement to prepare and execute. * @param mixed ...$args Values to bind to the statement, fetch mode for the statement, fetch mode options * - * @return \Generator + * @return Generator */ - public function yieldAll($stmt, ...$args) + public function yieldAll(Select|string $stmt, ...$args): Generator { $values = null; @@ -345,9 +347,9 @@ public function yieldAll($stmt, ...$args) * @param Select|string $stmt The SQL statement to prepare and execute * @param ?array $values Values to bind to the statement * - * @return \Generator + * @return Generator */ - public function yieldCol($stmt, ?array $values = null) + public function yieldCol(Select|string $stmt, ?array $values = null): Generator { $sth = $this->prepexec($stmt, $values); @@ -364,16 +366,16 @@ public function yieldCol($stmt, ?array $values = null) * @param Select|string $stmt The SQL statement to prepare and execute * @param ?array $values Values to bind to the statement * - * @return \Generator + * @return Generator */ - public function yieldPairs($stmt, ?array $values = null) + public function yieldPairs(Select|string $stmt, ?array $values = null): Generator { $sth = $this->prepexec($stmt, $values); $sth->setFetchMode(PDO::FETCH_NUM); foreach ($sth as $row) { - list($key, $value) = $row; + [$key, $value] = $row; yield $key => $value; } @@ -382,8 +384,8 @@ public function yieldPairs($stmt, ?array $values = null) /** * Prepare and execute the given statement * - * @param Delete|Insert|Select|Update|string $stmt The SQL statement to prepare and execute - * @param string|array $values Values to bind to the statement, if any + * @param Delete|Insert|Select|Update|string $stmt The SQL statement to prepare and execute + * @param string|array $values Values to bind to the statement, if any * * @return PDOStatement */ @@ -394,7 +396,7 @@ public function prepexec($stmt, $values = null) } if (is_object($stmt)) { - list($stmt, $values) = $this->getQueryBuilder()->assemble($stmt); + [$stmt, $values] = $this->getQueryBuilder()->assemble($stmt); } $this->connect(); @@ -412,9 +414,9 @@ public function prepexec($stmt, $values = null) * * @return PDOStatement */ - public function select(Select $select) + public function select(Select $select): PDOStatement { - list($stmt, $values) = $this->getQueryBuilder()->assembleSelect($select); + [$stmt, $values] = $this->getQueryBuilder()->assembleSelect($select); return $this->prepexec($stmt, $values); } @@ -422,7 +424,7 @@ public function select(Select $select) /** * Insert a table row with the specified data * - * @param string $table The table to insert data into. The table specification must be in + * @param string $table The table to insert data into. The table specification must be in * one of the following formats: 'table' or 'schema.table' * @param iterable $data Row data in terms of column-value pairs * @@ -430,7 +432,7 @@ public function select(Select $select) * * @throws InvalidArgumentException If data type is invalid */ - public function insert($table, $data) + public function insert(string $table, iterable $data): PDOStatement { $insert = (new Insert()) ->into($table) @@ -461,20 +463,24 @@ public function lastInsertId(?string $name = null): false|string /** * Update table rows with the specified data, optionally based on a given condition * - * @param string|array $table The table to update. The table specification must be in one of + * @param array|string $table The table to update. The table specification must be in one of * the following formats: * 'table', 'table alias', ['alias' => 'table'] - * @param iterable $data The columns to update in terms of column-value pairs - * @param mixed $condition The WHERE condition - * @param string $operator The operator to combine multiple conditions with, + * @param iterable $data The columns to update in terms of column-value pairs + * @param array|string|null $condition The WHERE condition + * @param string $operator The operator to combine multiple conditions with, * if the condition is in the array format * * @return PDOStatement * * @throws InvalidArgumentException If data type is invalid */ - public function update($table, $data, $condition = null, $operator = Sql::ALL) - { + public function update( + array|string $table, + iterable $data, + array|string|null $condition = null, + string $operator = Sql::ALL + ): PDOStatement { $update = (new Update()) ->table($table) ->set($data); @@ -489,16 +495,19 @@ public function update($table, $data, $condition = null, $operator = Sql::ALL) /** * Delete table rows, optionally based on a given condition * - * @param string|array $table The table to delete data from. The table specification must be in one of the + * @param array|string $table The table to delete data from. The table specification must be in one of the * following formats: 'table', 'table alias', ['alias' => 'table'] - * @param mixed $condition The WHERE condition - * @param string $operator The operator to combine multiple conditions with, + * @param array|string|null $condition The WHERE condition + * @param string $operator The operator to combine multiple conditions with, * if the condition is in the array format * * @return PDOStatement */ - public function delete($table, $condition = null, $operator = Sql::ALL) - { + public function delete( + array|string $table, + array|string|null $condition = null, + string $operator = Sql::ALL + ): PDOStatement { $delete = (new Delete()) ->from($table); @@ -514,7 +523,7 @@ public function delete($table, $condition = null, $operator = Sql::ALL) * * @return bool Whether the transaction was started successfully */ - public function beginTransaction() + public function beginTransaction(): bool { $this->connect(); @@ -526,7 +535,7 @@ public function beginTransaction() * * @return bool Whether the transaction was committed successfully */ - public function commitTransaction() + public function commitTransaction(): bool { return $this->pdo->commit(); } @@ -536,7 +545,7 @@ public function commitTransaction() * * @return bool Whether the transaction was rolled back successfully */ - public function rollBackTransaction() + public function rollBackTransaction(): bool { return $this->pdo->rollBack(); } @@ -551,7 +560,7 @@ public function rollBackTransaction() * * @throws Exception If an error occurs when running the callback */ - public function transaction(callable $callback) + public function transaction(callable $callback): mixed { $this->beginTransaction(); @@ -567,8 +576,8 @@ public function transaction(callable $callback) return $result; } - public function quoteIdentifier($identifier) + public function quoteIdentifier(array|string $identifiers): string { - return $this->getAdapter()->quoteIdentifier($identifier); + return $this->getAdapter()->quoteIdentifier($identifiers); } } diff --git a/src/Contract/Adapter.php b/src/Contract/Adapter.php index 6142626..4be8ea7 100644 --- a/src/Contract/Adapter.php +++ b/src/Contract/Adapter.php @@ -15,7 +15,7 @@ interface Adapter extends Quoter * * @return string */ - public function getDsn(Config $config); + public function getDsn(Config $config): string; /** * Get the PDO connect options based on the specified connection configuration @@ -24,7 +24,7 @@ public function getDsn(Config $config); * * @return array */ - public function getOptions(Config $config); + public function getOptions(Config $config): array; /** * Set the client time zone @@ -33,7 +33,7 @@ public function getOptions(Config $config); * * @return $this */ - public function setClientTimezone(Connection $db); + public function setClientTimezone(Connection $db): static; /** * Register callbacks for query builder events @@ -42,5 +42,5 @@ public function setClientTimezone(Connection $db); * * @return $this */ - public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder); + public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder): static; } diff --git a/src/Contract/Quoter.php b/src/Contract/Quoter.php index 79c4c78..08dda06 100644 --- a/src/Contract/Quoter.php +++ b/src/Contract/Quoter.php @@ -17,5 +17,5 @@ interface Quoter * * @return string */ - public function quoteIdentifier($identifiers); + public function quoteIdentifier(array|string $identifiers): string; } diff --git a/src/Cursor.php b/src/Cursor.php index 85c5b1c..4df790a 100644 --- a/src/Cursor.php +++ b/src/Cursor.php @@ -12,13 +12,13 @@ class Cursor implements IteratorAggregate, Paginatable { /** @var Connection */ - protected $db; + protected Connection $db; /** @var Select */ - protected $select; + protected Select $select; /** @var array */ - protected $fetchModeAndArgs = []; + protected array $fetchModeAndArgs = []; /** * Create a new cursor for the given connection and query @@ -37,7 +37,7 @@ public function __construct(Connection $db, Select $select) * * @return array */ - public function getFetchMode() + public function getFetchMode(): array { return $this->fetchModeAndArgs; } @@ -45,13 +45,13 @@ public function getFetchMode() /** * Set the fetch mode * - * @param int $fetchMode Fetch mode as one of the PDO fetch mode constants. + * @param int $fetchMode Fetch mode as one of the PDO fetch mode constants. * Please see {@link https://www.php.net/manual/en/pdostatement.setfetchmode} for details * @param mixed ...$args Fetch mode arguments * * @return $this */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode(int $fetchMode, ...$args): static { array_unshift($args, $fetchMode); @@ -65,34 +65,34 @@ public function getIterator(): Traversable return $this->db->yieldAll($this->select, ...$this->getFetchMode()); } - public function hasLimit() + public function hasLimit(): bool { return $this->select->hasLimit(); } - public function getLimit() + public function getLimit(): ?int { return $this->select->getLimit(); } - public function limit($limit) + public function limit(?int $limit): static { $this->select->limit($limit); return $this; } - public function hasOffset() + public function hasOffset(): bool { return $this->select->hasOffset(); } - public function getOffset() + public function getOffset(): ?int { return $this->select->getOffset(); } - public function offset($offset) + public function offset(?int $offset): static { $this->select->offset($offset); diff --git a/src/Delete.php b/src/Delete.php index 53736b8..15fb33f 100644 --- a/src/Delete.php +++ b/src/Delete.php @@ -10,15 +10,15 @@ class Delete implements CommonTableExpressionInterface, WhereInterface use CommonTableExpression; use Where; - /** @var array|null The FROM part of the DELETE query */ - protected $from; + /** @var ?array The FROM part of the DELETE query */ + protected ?array $from = null; /** * Get the FROM part of the DELETE query * - * @return array|null + * @return ?array */ - public function getFrom() + public function getFrom(): ?array { return $this->from; } @@ -32,12 +32,12 @@ public function getFrom() * If you are using special table names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|array $table The table to delete data from. The table specification must be in one of the + * @param array|string $table The table to delete data from. The table specification must be in one of the * following formats: 'table', 'table alias', ['alias' => 'table'] * * @return $this */ - public function from($table) + public function from(array|string $table): static { $this->from = ! is_array($table) ? [$table] : $table; diff --git a/src/Expression.php b/src/Expression.php index 0f544b1..6edb266 100644 --- a/src/Expression.php +++ b/src/Expression.php @@ -8,13 +8,13 @@ class Expression implements ExpressionInterface { /** @var string The statement of the expression */ - protected $statement; + protected string $statement; - /** @var array The columns used by the expression */ - protected $columns; + /** @var ?array The columns used by the expression */ + protected ?array $columns; /** @var array The values for the expression */ - protected $values; + protected array $values; /** * Create a new database expression @@ -23,31 +23,31 @@ class Expression implements ExpressionInterface * @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(string $statement, ?array $columns = null, ...$values) { $this->statement = $statement; $this->columns = $columns; $this->values = $values; } - public function getStatement() + public function getStatement(): string { return $this->statement; } - public function getColumns() + public function getColumns(): array { return $this->columns ?: []; } - public function setColumns(array $columns) + public function setColumns(array $columns): static { $this->columns = $columns; return $this; } - public function getValues() + public function getValues(): array { return $this->values; } diff --git a/src/ExpressionInterface.php b/src/ExpressionInterface.php index 9ebe5ee..9c994d6 100644 --- a/src/ExpressionInterface.php +++ b/src/ExpressionInterface.php @@ -12,14 +12,14 @@ interface ExpressionInterface * * @return string */ - public function getStatement(); + public function getStatement(): string; /** * Get the columns used by the expression * * @return array */ - public function getColumns(); + public function getColumns(): array; /** * Set the columns to use by the expression @@ -28,12 +28,12 @@ public function getColumns(); * * @return $this */ - public function setColumns(array $columns); + public function setColumns(array $columns): static; /** * Get the values for the expression * * @return array */ - public function getValues(); + public function getValues(): array; } diff --git a/src/Filter/In.php b/src/Filter/In.php index c126af6..30a1231 100644 --- a/src/Filter/In.php +++ b/src/Filter/In.php @@ -15,7 +15,7 @@ class In extends Filter\Condition * @param string[]|string $column * @param Select $select */ - public function __construct($column, Select $select) + public function __construct(array|string $column, Select $select) { $this ->setColumn($column) diff --git a/src/Filter/InAndNotInUtils.php b/src/Filter/InAndNotInUtils.php index 6f26de1..26349a6 100644 --- a/src/Filter/InAndNotInUtils.php +++ b/src/Filter/InAndNotInUtils.php @@ -17,7 +17,7 @@ trait InAndNotInUtils * * @return string[]|string */ - public function getColumn() + public function getColumn(): array|string { return $this->column; } @@ -29,7 +29,7 @@ public function getColumn() * * @return $this */ - public function setColumn($column): self + public function setColumn(array|string $column): self { $this->column = $column; @@ -53,7 +53,7 @@ public function getValue(): Select * * @return $this */ - public function setValue($value): self + public function setValue(Select $value): self { $this->value = $value; diff --git a/src/Filter/NotIn.php b/src/Filter/NotIn.php index cdf6241..a8be67f 100644 --- a/src/Filter/NotIn.php +++ b/src/Filter/NotIn.php @@ -15,7 +15,7 @@ class NotIn extends Filter\Condition * @param string[]|string $column * @param Select $select */ - public function __construct($column, Select $select) + public function __construct(array|string $column, Select $select) { $this ->setColumn($column) diff --git a/src/Insert.php b/src/Insert.php index 738a842..4ee0137 100644 --- a/src/Insert.php +++ b/src/Insert.php @@ -13,24 +13,24 @@ class Insert implements CommonTableExpressionInterface { use CommonTableExpression; - /** @var string|null The table for the INSERT INTO query */ - protected $into; + /** @var ?string The table for the INSERT INTO query */ + protected ?string $into = null; - /** @var array|null The columns for which the query provides values */ - protected $columns; + /** @var ?array The columns for which the query provides values */ + protected ?array $columns = null; - /** @var array|null The values to insert */ - protected $values; + /** @var ?array $values The values to insert */ + protected ?array $values = null; - /** @var Select|null The select query for INSERT INTO ... SELECT queries */ - protected $select; + /** @var ?Select The select query for INSERT INTO ... SELECT queries */ + protected ?Select $select = null; /** * Get the table for the INSERT INTo query * - * @return string|null + * @return ?string */ - public function getInto() + public function getInto(): ?string { return $this->into; } @@ -49,7 +49,7 @@ public function getInto() * * @return $this */ - public function into($table) + public function into(string $table): static { $this->into = $table; @@ -61,7 +61,7 @@ public function into($table) * * @return array */ - public function getColumns() + public function getColumns(): array { if (! empty($this->columns)) { return array_keys($this->columns); @@ -90,7 +90,7 @@ public function getColumns() * * @return $this */ - public function columns(array $columns) + public function columns(array $columns): static { $this->columns = array_flip($columns); @@ -102,7 +102,7 @@ public function columns(array $columns) * * @return array */ - public function getValues() + public function getValues(): array { return array_values($this->values ?: []); } @@ -135,7 +135,7 @@ public function values($values) * * @return $this */ - public function select(Select $select) + public function select(Select $select): static { $this->select = $select; @@ -145,9 +145,9 @@ public function select(Select $select) /** * Get the select query for the INSERT INTO ... SELECT statement * - * @return Select|null + * @return ?Select */ - public function getSelect() + public function getSelect(): ?Select { return $this->select; } diff --git a/src/LimitOffset.php b/src/LimitOffset.php index 99c30a2..254314b 100644 --- a/src/LimitOffset.php +++ b/src/LimitOffset.php @@ -12,75 +12,61 @@ trait LimitOffset * * If unset or lower than 0, no limit will be applied. * - * @var int|null + * @var ?int */ - protected $limit; + protected ?int $limit = null; /** * Offset from where to start the result set * * If unset or lower than 0, the result set will start from the beginning. * - * @var int|null + * @var ?int */ - protected $offset; + protected ?int $offset = null; - public function hasLimit() + public function hasLimit(): bool { return $this->limit !== null; } - public function getLimit() + public function getLimit(): ?int { return $this->limit; } - public function limit($limit) + public function limit(?int $limit): static { - if ($limit !== null) { - $limit = (int) $limit; - if ($limit < 0) { - $limit = null; - } - } - - $this->limit = $limit; + $this->limit = $limit < 0 ? null : $limit; return $this; } - public function resetLimit() + public function resetLimit(): static { $this->limit = null; return $this; } - public function hasOffset() + public function hasOffset(): bool { return $this->offset !== null; } - public function getOffset() + public function getOffset(): ?int { return $this->offset; } - public function offset($offset) + public function offset(?int $offset): static { - if ($offset !== null) { - $offset = (int) $offset; - if ($offset <= 0) { - $offset = null; - } - } - - $this->offset = $offset; + $this->offset = $offset <= 0 ? null : $offset; return $this; } - public function resetOffset() + public function resetOffset(): static { $this->offset = null; diff --git a/src/LimitOffsetInterface.php b/src/LimitOffsetInterface.php index 94628c4..4dede24 100644 --- a/src/LimitOffsetInterface.php +++ b/src/LimitOffsetInterface.php @@ -12,60 +12,60 @@ interface LimitOffsetInterface * * @return bool */ - public function hasLimit(); + public function hasLimit(): bool; /** * Get the limit * - * @return int|null + * @return ?int */ - public function getLimit(); + public function getLimit(): ?int; /** * Set the limit * - * @param int|null $limit Maximum number of items to return. + * @param ?int $limit Maximum number of items to return. * If you want to disable the limit, use null or a negative value * * @return $this */ - public function limit($limit); + public function limit(?int $limit): static; /** * Reset the limit * * @return $this */ - public function resetLimit(); + public function resetLimit(): static; /** * Get whether an offset is configured * * @return bool */ - public function hasOffset(); + public function hasOffset(): bool; /** * Get the offset * - * @return int|null + * @return ?int */ - public function getOffset(); + public function getOffset(): ?int; /** * Set the offset * - * @param int|null $offset Start result set after this many rows. + * @param ?int $offset Start result set after this many rows. * If you want to disable the offset, use null, 0, or a negative value * * @return $this */ - public function offset($offset); + public function offset(?int $offset): static; /** * Reset the offset * * @return $this */ - public function resetOffset(); + public function resetOffset(): static; } diff --git a/src/OrderBy.php b/src/OrderBy.php index a19d7c5..822a8fa 100644 --- a/src/OrderBy.php +++ b/src/OrderBy.php @@ -8,19 +8,19 @@ trait OrderBy { /** @var ?array ORDER BY part of the query */ - protected $orderBy; + protected ?array $orderBy = null; - public function hasOrderBy() + public function hasOrderBy(): bool { return $this->orderBy !== null; } - public function getOrderBy() + public function getOrderBy(): ?array { return $this->orderBy; } - public function orderBy($orderBy, $direction = null) + public function orderBy($orderBy, int|string|null $direction = null): static { if (! is_array($orderBy)) { $orderBy = [$orderBy]; @@ -48,7 +48,7 @@ public function orderBy($orderBy, $direction = null) return $this; } - public function resetOrderBy() + public function resetOrderBy(): static { $this->orderBy = null; @@ -60,7 +60,7 @@ public function resetOrderBy() * * Shall be called by using classes in their __clone() */ - protected function cloneOrderBy() + protected function cloneOrderBy(): void { if ($this->orderBy !== null) { foreach ($this->orderBy as &$orderBy) { diff --git a/src/OrderByInterface.php b/src/OrderByInterface.php index 0ee0dda..37588df 100644 --- a/src/OrderByInterface.php +++ b/src/OrderByInterface.php @@ -12,14 +12,14 @@ interface OrderByInterface * * @return bool */ - public function hasOrderBy(); + public function hasOrderBy(): bool; /** * Get the ORDER BY part of the query * - * @return array|null + * @return ?array */ - public function getOrderBy(); + public function getOrderBy(): ?array; /** * Set the ORDER BY part of the query - either plain columns or expressions or scalar subqueries @@ -33,19 +33,19 @@ public function getOrderBy(); * If you are using special field names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|int|array $orderBy The ORDER BY part. The items can be in any format of the following: + * @param int|array|string $orderBy The ORDER BY part. The items can be in any format of the following: * ['column', 'column' => 'DESC', 'column' => SORT_DESC, ['column', 'DESC']] - * @param string|int $direction The default direction. Can be any of the following: + * @param int|string|null $direction The default direction. Can be any of the following: * 'ASC', 'DESC', SORT_ASC, SORT_DESC * * @return $this */ - public function orderBy($orderBy, $direction = null); + public function orderBy($orderBy, int|string|null $direction = null): static; /** * Reset the ORDER BY part of the query * * @return $this */ - public function resetOrderBy(); + public function resetOrderBy(): static; } diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index f65c68c..3f3f2c5 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -141,9 +141,9 @@ class QueryBuilder public const ON_DELETE_ASSEMBLED = 'deleteAssembled'; /** @var Adapter */ - protected $adapter; + protected Adapter $adapter; - protected $separator = " "; + protected string $separator = " "; /** * Create a new query builder for the specified database adapter @@ -166,7 +166,7 @@ public function __construct(Adapter $adapter) * * @throw InvalidArgumentException If statement type is invalid */ - public function assemble($stmt) + public function assemble(Select|Insert|Update|Delete $stmt): array { switch (true) { case $stmt instanceof Delete: @@ -192,7 +192,7 @@ public function assemble($stmt) * * @return array */ - public function assembleDelete(Delete $delete) + public function assembleDelete(Delete $delete): array { $values = []; @@ -218,7 +218,7 @@ public function assembleDelete(Delete $delete) * * @return array */ - public function assembleInsert(Insert $insert) + public function assembleInsert(Insert $insert): array { $values = []; @@ -249,7 +249,7 @@ public function assembleInsert(Insert $insert) * * @return array */ - public function assembleSelect(Select $select, array &$values = []) + public function assembleSelect(Select $select, array &$values = []): array { $select = clone $select; @@ -271,7 +271,7 @@ public function assembleSelect(Select $select, array &$values = []) $unions = $this->buildUnions($select->getUnion(), $values); if ($unions) { - list($unionKeywords, $selects) = $unions; + [$unionKeywords, $selects] = $unions; if ($sql) { $sql = "($sql)"; @@ -307,7 +307,7 @@ public function assembleSelect(Select $select, array &$values = []) * * @return array */ - public function assembleUpdate(Update $update) + public function assembleUpdate(Update $update): array { $values = []; @@ -335,7 +335,7 @@ public function assembleUpdate(Update $update) * * @return string The WITH part of a query */ - public function buildWith(array $with, array &$values) + public function buildWith(array $with, array &$values): string { if (empty($with)) { return ''; @@ -345,8 +345,8 @@ public function buildWith(array $with, array &$values) $hasRecursive = false; foreach ($with as $cte) { - list($query, $alias, $recursive) = $cte; - list($cteSql, $cteValues) = $this->assembleSelect($query); + [$query, $alias, $recursive] = $cte; + [$cteSql, $cteValues] = $this->assembleSelect($query); $ctes[] = "$alias AS ($cteSql)"; @@ -364,7 +364,7 @@ public function buildWith(array $with, array &$values) * * @return string The DELETE FROM part of a query */ - public function buildDeleteFrom(?array $from = null) + public function buildDeleteFrom(?array $from = null): string { if ($from === null) { return ''; @@ -393,7 +393,7 @@ public function buildDeleteFrom(?array $from = null) * * @return array */ - public function unpackCondition($expression, array $values) + public function unpackCondition(string $expression, array $values): array { $placeholders = preg_match_all('/(\?)/', $expression, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); @@ -440,7 +440,7 @@ public function unpackCondition($expression, array $values) * * @return string */ - public function buildCondition(array $condition, array &$values) + public function buildCondition(array $condition, array &$values): string { $sql = []; @@ -491,7 +491,7 @@ public function buildCondition(array $condition, 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 = []): string { if ($where === null) { return ''; @@ -507,7 +507,7 @@ public function buildWhere(?array $where = null, array &$values = []) * * @return string The INSERT INTO part of a INSERT INTO ... statement */ - public function buildInsertInto($into) + public function buildInsertInto(?string $into): string { if (empty($into)) { return ''; @@ -525,7 +525,7 @@ public function buildInsertInto($into) * * @return string The columns and SELECT part of the INSERT INTO ... SELECT statement */ - public function buildInsertIntoSelect(array $columns, Select $select, array &$values) + public function buildInsertIntoSelect(array $columns, Select $select, array &$values): string { $sql = [ '(' . implode(',', $columns) . ')', @@ -544,7 +544,7 @@ public function buildInsertIntoSelect(array $columns, Select $select, array &$va * * @return string The columns and values part of a INSERT INTO ... statement */ - public function buildInsertColumnsAndValues(array $columns, array $insertValues, array &$values) + public function buildInsertColumnsAndValues(array $columns, array $insertValues, array &$values): string { $sql = ['(' . implode(',', $columns) . ')']; @@ -570,12 +570,12 @@ public function buildInsertColumnsAndValues(array $columns, array $insertValues, * Build the SELECT part of a query * * @param array $columns - * @param bool $distinct + * @param bool $distinct * @param array $values * * @return string The SELECT part of the query */ - public function buildSelect(array $columns, $distinct, array &$values) + public function buildSelect(array $columns, bool $distinct, array &$values): string { if (empty($columns)) { return ''; @@ -614,7 +614,7 @@ public function buildSelect(array $columns, $distinct, 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 = []): string { if ($from === null) { return ''; @@ -640,12 +640,13 @@ public function buildFrom(?array $from = null, array &$values = []) /** * Build the JOIN part(s) of a query * - * @param array $joins + * @param ?array $joins + * * @oaram array $values * * @return string The JOIN part(s) of the query */ - public function buildJoin($joins, array &$values) + public function buildJoin(?array $joins, array &$values): string { if ($joins === null) { return ''; @@ -653,7 +654,7 @@ public function buildJoin($joins, array &$values) $sql = []; foreach ($joins as $join) { - list($joinType, $table, $condition) = $join; + [$joinType, $table, $condition] = $join; if (is_array($table)) { $tableName = null; @@ -691,7 +692,7 @@ public function buildJoin($joins, 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 = []): string { if ($groupBy === null) { return ''; @@ -716,7 +717,7 @@ public function buildGroupBy(?array $groupBy = null, 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 = []): string { if ($having === null) { return ''; @@ -733,7 +734,7 @@ public function buildHaving(?array $having = null, 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 = []): string { if ($orderBy === null) { return ''; @@ -742,7 +743,7 @@ public function buildOrderBy(?array $orderBy = null, array &$values = []) $sql = []; foreach ($orderBy as $column) { - list($column, $direction) = $column; + [$column, $direction] = $column; if ($column instanceof ExpressionInterface) { $column = $this->buildExpression($column, $values); @@ -763,12 +764,12 @@ public function buildOrderBy(?array $orderBy = null, array &$values = []) /** * Build the LIMIT and OFFSET part of a query * - * @param int $limit - * @param int $offset + * @param ?int $limit + * @param ?int $offset * * @return string The LIMIT and OFFSET part of the query */ - public function buildLimitOffset($limit = null, $offset = null) + public function buildLimitOffset(?int $limit = null, ?int $offset = null): string { $sql = []; @@ -801,9 +802,9 @@ public function buildLimitOffset($limit = null, $offset = null) * @param ?array $unions * @param array $values * - * @return array|null The UNION parts of the query + * @return ?array The UNION parts of the query */ - public function buildUnions(?array $unions = null, array &$values = []) + public function buildUnions(?array $unions = null, array &$values = []): ?array { if ($unions === null) { return null; @@ -813,10 +814,10 @@ public function buildUnions(?array $unions = null, array &$values = []) $selects = []; foreach ($unions as $union) { - list($select, $all) = $union; + [$select, $all] = $union; if ($select instanceof Select) { - list($select, $values) = $this->assembleSelect($select, $values); + [$select, $values] = $this->assembleSelect($select, $values); } $unionKeywords[] = ($all ? 'UNION ALL' : 'UNION'); @@ -833,7 +834,7 @@ public function buildUnions(?array $unions = null, array &$values = []) * * @return string The UPDATE {table} part of the query */ - public function buildUpdateTable(?array $updateTable = null) + public function buildUpdateTable(?array $updateTable = null): string { if ($updateTable === null) { return ''; @@ -862,7 +863,7 @@ public function buildUpdateTable(?array $updateTable = null) * * @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 = []): string { if (empty($set)) { return ''; @@ -892,7 +893,7 @@ public function buildUpdateSet(?array $set = null, array &$values = []) * * @return string The expression's statement */ - public function buildExpression(ExpressionInterface $expression, array &$values = []) + public function buildExpression(ExpressionInterface $expression, array &$values = []): string { $stmt = $expression->getStatement(); $columns = $expression->getColumns(); diff --git a/src/Select.php b/src/Select.php index f56a131..ecf3a62 100644 --- a/src/Select.php +++ b/src/Select.php @@ -13,13 +13,13 @@ class Select implements CommonTableExpressionInterface, LimitOffsetInterface, Or use Where; /** @var bool Whether the query is DISTINCT */ - protected $distinct = false; + protected bool $distinct = false; - /** @var array|null The columns for the SELECT query */ - protected $columns; + /** @var ?array The columns for the SELECT query */ + protected ?array $columns = null; - /** @var array|null FROM part of the query, i.e. the table names to select data from */ - protected $from; + /** @var ?array FROM part of the query, i.e. the table names to select data from */ + protected ?array $from = null; /** * The tables to JOIN @@ -31,13 +31,13 @@ class Select implements CommonTableExpressionInterface, LimitOffsetInterface, Or * * @var ?array */ - protected $join; + protected ?array $join = null; - /** @var array|null The columns for the GROUP BY part of the query */ - protected $groupBy; + /** @var ?array The columns for the GROUP BY part of the query */ + protected ?array $groupBy = null; - /** @var array|null Internal representation for the HAVING part of the query */ - protected $having; + /** @var ?array Internal representation for the HAVING part of the query */ + protected ?array $having = null; /** * The queries to UNION @@ -49,14 +49,14 @@ class Select implements CommonTableExpressionInterface, LimitOffsetInterface, Or * * @var ?array */ - protected $union; + protected ?array $union = null; /** * Get whether to SELECT DISTINCT * * @return bool */ - public function getDistinct() + public function getDistinct(): bool { return $this->distinct; } @@ -68,7 +68,7 @@ public function getDistinct() * * @return $this */ - public function distinct($distinct = true) + public function distinct(bool $distinct = true): static { $this->distinct = $distinct; @@ -80,7 +80,7 @@ public function distinct($distinct = true) * * @return array */ - public function getColumns() + public function getColumns(): array { return $this->columns ?: []; } @@ -102,7 +102,7 @@ public function getColumns() * * @return $this */ - public function columns($columns) + public function columns($columns): static { if (! is_array($columns)) { $columns = [$columns]; @@ -116,9 +116,9 @@ public function columns($columns) /** * Get the FROM part of the query * - * @return array|null + * @return ?array */ - public function getFrom() + public function getFrom(): ?array { return $this->from; } @@ -139,7 +139,7 @@ public function getFrom() * * @return $this */ - public function from($tables) + public function from($tables): static { if (! is_array($tables)) { $tables = [$tables]; @@ -153,9 +153,9 @@ public function from($tables) /** * Get the JOIN part(s) of the query * - * @return array|null + * @return ?array */ - public function getJoin() + public function getJoin(): ?array { return $this->join; } @@ -174,7 +174,7 @@ public function getJoin() * * @return $this */ - public function join($table, $condition, $operator = Sql::ALL) + public function join($table, $condition, $operator = Sql::ALL): static { $this->join[] = ['INNER', $table, $this->buildCondition($condition, $operator)]; @@ -195,7 +195,7 @@ public function join($table, $condition, $operator = Sql::ALL) * * @return $this */ - public function joinLeft($table, $condition, $operator = Sql::ALL) + public function joinLeft($table, $condition, $operator = Sql::ALL): static { $this->join[] = ['LEFT', $table, $this->buildCondition($condition, $operator)]; @@ -216,7 +216,7 @@ public function joinLeft($table, $condition, $operator = Sql::ALL) * * @return $this */ - public function joinRight($table, $condition, $operator = Sql::ALL) + public function joinRight($table, $condition, $operator = Sql::ALL): static { $this->join[] = ['RIGHT', $table, $this->buildCondition($condition, $operator)]; @@ -226,9 +226,9 @@ public function joinRight($table, $condition, $operator = Sql::ALL) /** * Get the GROUP BY part of the query * - * @return array|null + * @return ?array */ - public function getGroupBy() + public function getGroupBy(): ?array { return $this->groupBy; } @@ -249,7 +249,7 @@ public function getGroupBy() * * @return $this */ - public function groupBy($groupBy) + public function groupBy($groupBy): static { $this->groupBy = array_merge( $this->groupBy === null ? [] : $this->groupBy, @@ -262,9 +262,9 @@ public function groupBy($groupBy) /** * Get the HAVING part of the query * - * @return array|null + * @return ?array */ - public function getHaving() + public function getHaving(): ?array { return $this->having; } @@ -291,7 +291,7 @@ public function getHaving() * * @return $this */ - public function having($condition, $operator = Sql::ALL) + public function having($condition, string $operator = Sql::ALL): static { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::ALL); @@ -309,7 +309,7 @@ public function having($condition, $operator = Sql::ALL) * * @return $this */ - public function orHaving($condition, $operator = Sql::ALL) + public function orHaving($condition, string $operator = Sql::ALL): static { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::ANY); @@ -327,7 +327,7 @@ public function orHaving($condition, $operator = Sql::ALL) * * @return $this */ - public function notHaving($condition, $operator = Sql::ALL) + public function notHaving($condition, string $operator = Sql::ALL) { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::NOT_ALL); @@ -345,7 +345,7 @@ public function notHaving($condition, $operator = Sql::ALL) * * @return $this */ - public function orNotHaving($condition, $operator = Sql::ALL) + public function orNotHaving($condition, string $operator = Sql::ALL) { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::NOT_ANY); @@ -355,9 +355,9 @@ public function orNotHaving($condition, $operator = Sql::ALL) /** * Get the UNION parts of the query * - * @return array|null + * @return ?array */ - public function getUnion() + public function getUnion(): ?array { return $this->union; } @@ -365,11 +365,11 @@ public function getUnion() /** * Combine a query with UNION * - * @param Select|string $query + * @param string|Select $query * * @return $this */ - public function union($query) + public function union(Select|string $query): static { $this->union[] = [$query, false]; @@ -379,11 +379,11 @@ public function union($query) /** * Combine a query with UNION ALL * - * @param Select|string $query + * @param string|Select $query * * @return $this */ - public function unionAll($query) + public function unionAll(Select|string $query): static { $this->union[] = [$query, true]; @@ -395,7 +395,7 @@ public function unionAll($query) * * @return $this */ - public function resetDistinct() + public function resetDistinct(): static { $this->distinct = false; @@ -407,7 +407,7 @@ public function resetDistinct() * * @return $this */ - public function resetColumns() + public function resetColumns(): static { $this->columns = null; @@ -419,7 +419,7 @@ public function resetColumns() * * @return $this */ - public function resetFrom() + public function resetFrom(): static { $this->from = null; @@ -431,7 +431,7 @@ public function resetFrom() * * @return $this */ - public function resetJoin() + public function resetJoin(): static { $this->join = null; @@ -443,7 +443,7 @@ public function resetJoin() * * @return $this */ - public function resetGroupBy() + public function resetGroupBy(): static { $this->groupBy = null; @@ -455,7 +455,7 @@ public function resetGroupBy() * * @return $this */ - public function resetHaving() + public function resetHaving(): static { $this->having = null; @@ -467,7 +467,7 @@ public function resetHaving() * * @return $this */ - public function resetUnion() + public function resetUnion(): static { $this->union = null; @@ -479,7 +479,7 @@ public function resetUnion() * * @return Select */ - public function getCountQuery() + public function getCountQuery(): Select|static { $countQuery = clone $this; diff --git a/src/Sql.php b/src/Sql.php index 000a43a..bb90bff 100644 --- a/src/Sql.php +++ b/src/Sql.php @@ -33,7 +33,7 @@ class Sql * * @return Delete */ - public static function delete() + public static function delete(): Delete { return new Delete(); } @@ -43,7 +43,7 @@ public static function delete() * * @return Insert */ - public static function insert() + public static function insert(): Insert { return new Insert(); } @@ -53,7 +53,7 @@ public static function insert() * * @return Select */ - public static function select() + public static function select(): Select { return new Select(); } @@ -63,7 +63,7 @@ public static function select() * * @return Update */ - public static function update() + public static function update(): Update { return new Update(); } diff --git a/src/Test/TestConnection.php b/src/Test/TestConnection.php index 11d0117..aabf523 100644 --- a/src/Test/TestConnection.php +++ b/src/Test/TestConnection.php @@ -3,6 +3,10 @@ namespace ipl\Sql\Test; use ipl\Sql\Connection; +use ipl\Sql\Delete; +use ipl\Sql\Insert; +use ipl\Sql\Select; +use ipl\Sql\Update; /** * Config-less test connection @@ -14,22 +18,22 @@ public function __construct() $this->adapter = new TestAdapter(); } - public function connect() + public function connect(): static { return $this; } - public function beginTransaction() + public function beginTransaction(): bool { throw new \LogicException('Transactions are not supported by the test connection'); } - public function commitTransaction() + public function commitTransaction(): bool { throw new \LogicException('Transactions are not supported by the test connection'); } - public function rollbackTransaction() + public function rollbackTransaction(): bool { throw new \LogicException('Transactions are not supported by the test connection'); } diff --git a/src/Update.php b/src/Update.php index 356a610..af9ad53 100644 --- a/src/Update.php +++ b/src/Update.php @@ -14,18 +14,18 @@ class Update implements CommonTableExpressionInterface, WhereInterface use CommonTableExpression; use Where; - /** @var array|null The table for the UPDATE query */ - protected $table; + /** @var ?array The table for the UPDATE query */ + protected ?array $table = null; - /** @var array|null The columns to update in terms of column-value pairs */ - protected $set = []; + /** @var ?array The columns to update in terms of column-value pairs */ + protected ?array $set = []; /** * Get the table for the UPDATE query * - * @return array|null + * @return ?array */ - public function getTable() + public function getTable(): ?array { return $this->table; } @@ -39,12 +39,12 @@ public function getTable() * If you are using special table names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|array $table The table to update. The table specification must be in one of the + * @param array|string $table The table to update. The table specification must be in one of the * following formats: 'table', 'table alias', ['alias' => 'table'] * * @return $this */ - public function table($table) + public function table(array|string $table): static { $this->table = is_array($table) ? $table : [$table]; @@ -54,9 +54,9 @@ public function table($table) /** * Get the columns to update in terms of column-value pairs * - * @return array|null + * @return ?array */ - public function getSet() + public function getSet(): ?array { return $this->set; } @@ -78,7 +78,7 @@ public function getSet() * * @throws InvalidArgumentException If set type is invalid */ - public function set($set) + public function set($set): static { $this->set = arrayval($set); diff --git a/src/Where.php b/src/Where.php index f862846..404766c 100644 --- a/src/Where.php +++ b/src/Where.php @@ -7,47 +7,47 @@ */ trait Where { - /** @var array|null Internal representation for the WHERE part of the query */ - protected $where; + /** @var ?array Internal representation for the WHERE part of the query */ + protected ?array $where = null; - public function getWhere() + public function getWhere(): ?array { return $this->where; } - public function where($condition, ...$args) + public function where($condition, ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::ALL); return $this; } - public function orWhere($condition, ...$args) + public function orWhere($condition, ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::ANY); return $this; } - public function notWhere($condition, ...$args) + public function notWhere($condition, ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::NOT_ALL); return $this; } - public function orNotWhere($condition, ...$args) + public function orNotWhere($condition, ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::NOT_ANY); return $this; } - public function resetWhere() + public function resetWhere(): static { $this->where = null; @@ -64,7 +64,7 @@ public function resetWhere() * * @return array */ - protected function buildCondition($condition, $operator) + protected function buildCondition($condition, string $operator): array { if (is_array($condition)) { if (empty($condition)) { @@ -86,7 +86,7 @@ protected function buildCondition($condition, $operator) * @param array $condition As returned by {@link buildCondition()} * @param string $operator */ - protected function mergeCondition(&$base, array $condition, $operator) + protected function mergeCondition(&$base, array $condition, string $operator): void { if ($base === null) { $base = [$operator, [$condition]]; @@ -111,7 +111,7 @@ protected function mergeCondition(&$base, array $condition, $operator) * * @return array */ - protected function prepareConditionArguments($condition, array $args) + protected function prepareConditionArguments($condition, array $args): array { // Default operator $operator = Sql::ALL; @@ -132,7 +132,7 @@ protected function prepareConditionArguments($condition, array $args) * * Shall be called by using classes in their __clone() */ - protected function cloneWhere() + protected function cloneWhere(): void { if ($this->where !== null) { $this->cloneCondition($this->where); @@ -144,7 +144,7 @@ protected function cloneWhere() * * @param array $condition As returned by {@link buildCondition()} */ - protected function cloneCondition(array &$condition) + protected function cloneCondition(array &$condition): void { foreach ($condition as &$subCondition) { if (is_array($subCondition)) { diff --git a/src/WhereInterface.php b/src/WhereInterface.php index e724465..a74a8dc 100644 --- a/src/WhereInterface.php +++ b/src/WhereInterface.php @@ -10,9 +10,9 @@ interface WhereInterface /** * Get the WHERE part of the query * - * @return array|null + * @return ?array */ - public function getWhere(); + public function getWhere(): ?array; /** * Add a WHERE part of the query @@ -37,7 +37,7 @@ public function getWhere(); * * @return $this */ - public function where($condition, ...$args); + public function where($condition, ...$args): static; /** * Add a OR part to the WHERE part of the query @@ -49,7 +49,7 @@ public function where($condition, ...$args); * * @return $this */ - public function orWhere($condition, ...$args); + public function orWhere($condition, ...$args): static; /** * Add a AND NOT part to the WHERE part of the query @@ -61,7 +61,7 @@ public function orWhere($condition, ...$args); * * @return $this */ - public function notWhere($condition, ...$args); + public function notWhere($condition, ...$args): static; /** * Add a OR NOT part to the WHERE part of the query @@ -73,12 +73,12 @@ public function notWhere($condition, ...$args); * * @return $this */ - public function orNotWhere($condition, ...$args); + public function orNotWhere($condition, ...$args): static; /** * Reset the WHERE part of the query * * @return $this */ - public function resetWhere(); + public function resetWhere(): static; } From 00192235e37f727196ce3580df311644e87c7997 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Tue, 9 Dec 2025 14:15:28 +0100 Subject: [PATCH 08/11] Remove unnecessary trait `InAndNotInUtils` - This was only introduced to reduce phpstan errors. --- src/Filter/In.php | 6 +--- src/Filter/InAndNotInUtils.php | 62 ---------------------------------- src/Filter/NotIn.php | 6 +--- 3 files changed, 2 insertions(+), 72 deletions(-) delete mode 100644 src/Filter/InAndNotInUtils.php diff --git a/src/Filter/In.php b/src/Filter/In.php index 30a1231..2c8ce84 100644 --- a/src/Filter/In.php +++ b/src/Filter/In.php @@ -7,8 +7,6 @@ class In extends Filter\Condition { - use InAndNotInUtils; - /** * Create a new sql IN condition * @@ -17,8 +15,6 @@ class In extends Filter\Condition */ public function __construct(array|string $column, Select $select) { - $this - ->setColumn($column) - ->setValue($select); + parent::__construct($column, $select); } } diff --git a/src/Filter/InAndNotInUtils.php b/src/Filter/InAndNotInUtils.php deleted file mode 100644 index 26349a6..0000000 --- a/src/Filter/InAndNotInUtils.php +++ /dev/null @@ -1,62 +0,0 @@ -column; - } - - /** - * Set the columns of this condition - * - * @param string[]|string $column - * - * @return $this - */ - public function setColumn(array|string $column): self - { - $this->column = $column; - - return $this; - } - - /** - * Get the value of this condition - * - * @return Select - */ - public function getValue(): Select - { - return $this->value; - } - - /** - * Set the value of this condition - * - * @param Select $value - * - * @return $this - */ - public function setValue(Select $value): self - { - $this->value = $value; - - return $this; - } -} diff --git a/src/Filter/NotIn.php b/src/Filter/NotIn.php index a8be67f..e42909f 100644 --- a/src/Filter/NotIn.php +++ b/src/Filter/NotIn.php @@ -7,8 +7,6 @@ class NotIn extends Filter\Condition { - use InAndNotInUtils; - /** * Create a new sql NOT IN condition * @@ -17,8 +15,6 @@ class NotIn extends Filter\Condition */ public function __construct(array|string $column, Select $select) { - $this - ->setColumn($column) - ->setValue($select); + parent::__construct($column, $select); } } From 94364fa834e4ac784af63836390c4d775f94758c Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Wed, 10 Dec 2025 16:46:14 +0100 Subject: [PATCH 09/11] ConfigTest: `options` can only be an array --- tests/ConfigTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index 58d0324..4f3183e 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -52,7 +52,7 @@ public function testAllPropertiesCanBeSet(): void 'password' => 'test_password', 'use_ssl' => 'true', 'charset' => 'latin1', - 'options' => 'test_options', + 'options' => ['test_options'], 'ssl_key' => 'test_ssl_key', 'ssl_cert' => 'test_ssl_cert', 'ssl_ca' => 'test_ssl_ca', @@ -69,7 +69,7 @@ public function testAllPropertiesCanBeSet(): void $this->assertSame($config->password, 'test_password'); $this->assertSame($config->useSsl, 'true'); $this->assertSame($config->charset, 'latin1'); - $this->assertSame($config->options, 'test_options'); + $this->assertSame($config->options, ['test_options']); $this->assertSame($config->sslKey, 'test_ssl_key'); $this->assertSame($config->sslCert, 'test_ssl_cert'); $this->assertSame($config->sslCa, 'test_ssl_ca'); From 891337c64849a6806ac1a9f5bc8a898be7f5d2cf Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Wed, 10 Dec 2025 17:14:51 +0100 Subject: [PATCH 10/11] Replace switch statement with match expression - Remove now obsolete throw annotation and imports --- src/QueryBuilder.php | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index 3f3f2c5..24f5e6f 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -2,13 +2,10 @@ namespace ipl\Sql; -use InvalidArgumentException; use ipl\Sql\Adapter\Mssql; use ipl\Sql\Contract\Adapter; use ipl\Stdlib\Events; -use function ipl\Stdlib\get_php_type; - class QueryBuilder { use Events; @@ -163,26 +160,15 @@ public function __construct(Adapter $adapter) * @param Delete|Insert|Select|Update $stmt * * @return array - * - * @throw InvalidArgumentException If statement type is invalid */ public function assemble(Select|Insert|Update|Delete $stmt): array { - switch (true) { - case $stmt instanceof Delete: - return $this->assembleDelete($stmt); - case $stmt instanceof Insert: - return $this->assembleInsert($stmt); - case $stmt instanceof Select: - return $this->assembleSelect($stmt); - case $stmt instanceof Update: - return $this->assembleUpdate($stmt); - default: - throw new InvalidArgumentException(sprintf( - __METHOD__ . ' expects instances of Delete, Insert, Select or Update. Got %s instead.', - get_php_type($stmt) - )); - } + return match (true) { + $stmt instanceof Delete => $this->assembleDelete($stmt), + $stmt instanceof Insert => $this->assembleInsert($stmt), + $stmt instanceof Select => $this->assembleSelect($stmt), + $stmt instanceof Update => $this->assembleUpdate($stmt) + }; } /** From 214e28b6984b931c78cdcd4bd38a0e7dbe3bedaf Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Thu, 11 Dec 2025 15:34:34 +0100 Subject: [PATCH 11/11] Optimize Imports --- src/Test/TestConnection.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Test/TestConnection.php b/src/Test/TestConnection.php index aabf523..1e149b8 100644 --- a/src/Test/TestConnection.php +++ b/src/Test/TestConnection.php @@ -3,10 +3,6 @@ namespace ipl\Sql\Test; use ipl\Sql\Connection; -use ipl\Sql\Delete; -use ipl\Sql\Insert; -use ipl\Sql\Select; -use ipl\Sql\Update; /** * Config-less test connection