From 97ece99b4a1323d7d46ade2dc426e3f503f617db Mon Sep 17 00:00:00 2001 From: Adrian Liunardo Date: Wed, 8 Apr 2026 16:09:59 +0700 Subject: [PATCH 1/2] Fix for "Complex Where Conditions" https://github.com/tommyknocker/pdo-database-class/issues/20 --- src/query/ConditionBuilder.php | 44 ++++++++++++++++++++++++---------- src/query/QueryBuilder.php | 40 +++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/query/ConditionBuilder.php b/src/query/ConditionBuilder.php index 67457a52..423b819e 100644 --- a/src/query/ConditionBuilder.php +++ b/src/query/ConditionBuilder.php @@ -81,13 +81,13 @@ public function limit(int $number): static /** * Add WHERE clause. * - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * * @return static The current instance. */ - public function where(string|array|RawValue $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static + public function where(string|array|RawValue|\Closure $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static { return $this->addCondition(QueryConstants::COND_WHERE, $exprOrColumn, $value, $operator, QueryConstants::BOOLEAN_AND); } @@ -95,13 +95,13 @@ public function where(string|array|RawValue $exprOrColumn, mixed $value = null, /** * Add AND WHERE clause. * - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * * @return static The current instance. */ - public function andWhere(string|array|RawValue $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static + public function andWhere(string|array|RawValue|\Closure $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static { return $this->where($exprOrColumn, $value, $operator); } @@ -109,13 +109,13 @@ public function andWhere(string|array|RawValue $exprOrColumn, mixed $value = nul /** * Add OR WHERE clause. * - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * * @return static The current instance. */ - public function orWhere(string|array|RawValue $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static + public function orWhere(string|array|RawValue|\Closure $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static { return $this->addCondition(QueryConstants::COND_WHERE, $exprOrColumn, $value, $operator, QueryConstants::BOOLEAN_OR); } @@ -123,13 +123,13 @@ public function orWhere(string|array|RawValue $exprOrColumn, mixed $value = null /** * Add HAVING clause. * - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * * @return static The current instance. */ - public function having(string|array|RawValue $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static + public function having(string|array|RawValue|\Closure $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static { return $this->addCondition(QueryConstants::COND_HAVING, $exprOrColumn, $value, $operator, QueryConstants::BOOLEAN_AND); } @@ -137,13 +137,13 @@ public function having(string|array|RawValue $exprOrColumn, mixed $value = null, /** * Add OR HAVING clause. * - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * * @return static The current instance. */ - public function orHaving(string|array|RawValue $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static + public function orHaving(string|array|RawValue|\Closure $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static { return $this->addCondition(QueryConstants::COND_HAVING, $exprOrColumn, $value, $operator, QueryConstants::BOOLEAN_OR); } @@ -653,7 +653,7 @@ public function getHaving(): array * Add condition to the WHERE or HAVING clause. * * @param string $prop The property to add the condition to. - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @param string $cond The condition to use. @@ -662,11 +662,31 @@ public function getHaving(): array */ protected function addCondition( string $prop, - string|array|RawValue $exprOrColumn, + string|array|RawValue|\Closure $exprOrColumn, mixed $value, string $operator, string $cond ): static { + // Handle logical grouping via Closure + if ($exprOrColumn instanceof \Closure) { + $instance = new QueryBuilder($this->connection, $this->prefix ?? ''); + $exprOrColumn($instance); + + $subCb = $instance->getConditionBuilder(); + $items = ($prop === QueryConstants::COND_WHERE) ? $subCb->getWhere() : $subCb->getHaving(); + + if (!empty($items)) { + $sql = trim($this->buildConditionsClause($items, '')); + + $subParams = $instance->getParameterManager()->getParams(); + $map = $this->parameterManager->mergeSubParams($subParams, 'grp'); + $sql = $this->parameterManager->replacePlaceholdersInSql($sql, $map); + + $this->{$prop}[] = ['sql' => "({$sql})", 'cond' => $cond]; + } + return $this; + } + if (is_array($exprOrColumn)) { foreach ($exprOrColumn as $col => $val) { $exprQuoted = $this->quoteQualifiedIdentifier((string)$col); diff --git a/src/query/QueryBuilder.php b/src/query/QueryBuilder.php index 09b78279..37d2c02c 100644 --- a/src/query/QueryBuilder.php +++ b/src/query/QueryBuilder.php @@ -1360,13 +1360,13 @@ public function stream(): Generator /** * Add WHERE clause. * - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * * @return static The current instance. */ - public function where(string|array|RawValue $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static + public function where(string|array|RawValue|\Closure $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static { // Handle the old signature: where(array $conditions, array $params) if (is_array($exprOrColumn) && is_array($value) && $operator === QueryConstants::OP_EQUAL) { @@ -1393,13 +1393,13 @@ public function where(string|array|RawValue $exprOrColumn, mixed $value = null, /** * Add AND WHERE clause. * - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * * @return static The current instance. */ - public function andWhere(string|array|RawValue $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static + public function andWhere(string|array|RawValue|\Closure $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static { $this->conditionBuilder->andWhere($exprOrColumn, $value, $operator); return $this; @@ -1408,13 +1408,13 @@ public function andWhere(string|array|RawValue $exprOrColumn, mixed $value = nul /** * Add OR WHERE clause. * - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * * @return static The current instance. */ - public function orWhere(string|array|RawValue $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static + public function orWhere(string|array|RawValue|\Closure $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static { $this->conditionBuilder->orWhere($exprOrColumn, $value, $operator); return $this; @@ -1423,13 +1423,13 @@ public function orWhere(string|array|RawValue $exprOrColumn, mixed $value = null /** * Add HAVING clause. * - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * * @return static The current instance. */ - public function having(string|array|RawValue $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static + public function having(string|array|RawValue|\Closure $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static { $this->conditionBuilder->having($exprOrColumn, $value, $operator); return $this; @@ -1438,13 +1438,13 @@ public function having(string|array|RawValue $exprOrColumn, mixed $value = null, /** * Add OR HAVING clause. * - * @param string|array|RawValue $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * * @return static The current instance. */ - public function orHaving(string|array|RawValue $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static + public function orHaving(string|array|RawValue|\Closure $exprOrColumn, mixed $value = null, string $operator = QueryConstants::OP_EQUAL): static { $this->conditionBuilder->orHaving($exprOrColumn, $value, $operator); return $this; @@ -2644,4 +2644,24 @@ public function __call(string $name, array $arguments): mixed 'If you intended to call a macro, make sure it is registered using QueryBuilder::macro().' ); } + + /** + * Get the condition builder instance. + * + * @return ConditionBuilderInterface + */ + public function getConditionBuilder(): ConditionBuilderInterface + { + return $this->conditionBuilder; + } + + /** + * Get the parameter manager instance. + * + * @return ParameterManagerInterface + */ + public function getParameterManager(): ParameterManagerInterface + { + return $this->parameterManager; + } } From e96cde9484965cfb088261d2446ce7d582a94599 Mon Sep 17 00:00:00 2001 From: Adrian Liunardo Date: Wed, 8 Apr 2026 16:24:04 +0700 Subject: [PATCH 2/2] Fix PHPStan complaints --- src/query/ConditionBuilder.php | 12 ++++++------ src/query/QueryBuilder.php | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/query/ConditionBuilder.php b/src/query/ConditionBuilder.php index 423b819e..babc254d 100644 --- a/src/query/ConditionBuilder.php +++ b/src/query/ConditionBuilder.php @@ -81,7 +81,7 @@ public function limit(int $number): static /** * Add WHERE clause. * - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @@ -95,7 +95,7 @@ public function where(string|array|RawValue|\Closure $exprOrColumn, mixed $value /** * Add AND WHERE clause. * - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @@ -109,7 +109,7 @@ public function andWhere(string|array|RawValue|\Closure $exprOrColumn, mixed $va /** * Add OR WHERE clause. * - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @@ -123,7 +123,7 @@ public function orWhere(string|array|RawValue|\Closure $exprOrColumn, mixed $val /** * Add HAVING clause. * - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @@ -137,7 +137,7 @@ public function having(string|array|RawValue|\Closure $exprOrColumn, mixed $valu /** * Add OR HAVING clause. * - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @@ -653,7 +653,7 @@ public function getHaving(): array * Add condition to the WHERE or HAVING clause. * * @param string $prop The property to add the condition to. - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @param string $cond The condition to use. diff --git a/src/query/QueryBuilder.php b/src/query/QueryBuilder.php index 37d2c02c..ca92b4a8 100644 --- a/src/query/QueryBuilder.php +++ b/src/query/QueryBuilder.php @@ -1360,7 +1360,7 @@ public function stream(): Generator /** * Add WHERE clause. * - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @@ -1393,7 +1393,7 @@ public function where(string|array|RawValue|\Closure $exprOrColumn, mixed $value /** * Add AND WHERE clause. * - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @@ -1408,7 +1408,7 @@ public function andWhere(string|array|RawValue|\Closure $exprOrColumn, mixed $va /** * Add OR WHERE clause. * - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @@ -1423,7 +1423,7 @@ public function orWhere(string|array|RawValue|\Closure $exprOrColumn, mixed $val /** * Add HAVING clause. * - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. * @@ -1438,7 +1438,7 @@ public function having(string|array|RawValue|\Closure $exprOrColumn, mixed $valu /** * Add OR HAVING clause. * - * @param string|array|RawValue|\Closure $exprOrColumn The expression or column to add. + * @param string|array|RawValue|\Closure(QueryBuilder): void $exprOrColumn The expression or column to add. * @param mixed $value The value to use in the condition. * @param string $operator The operator to use in the condition. *