Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions src/Where.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,33 @@ public function getWhere()
return $this->where;
}

public function where($condition, $operator = Sql::ALL)
public function where($condition, ...$args)
{
list($condition, $operator) = $this->prepareConditionArguments($condition, $args);
$this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::ALL);

return $this;
}

public function orWhere($condition, $operator = Sql::ALL)
public function orWhere($condition, ...$args)
{
list($condition, $operator) = $this->prepareConditionArguments($condition, $args);
$this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::ANY);

return $this;
}

public function notWhere($condition, $operator = Sql::ALL)
public function notWhere($condition, ...$args)
{
list($condition, $operator) = $this->prepareConditionArguments($condition, $args);
$this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::NOT_ALL);

return $this;
}

public function orNotWhere($condition, $operator = Sql::ALL)
public function orNotWhere($condition, ...$args)
{
list($condition, $operator) = $this->prepareConditionArguments($condition, $args);
$this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::NOT_ANY);

return $this;
Expand Down Expand Up @@ -92,6 +96,30 @@ protected function mergeCondition(&$base, array $condition, $operator)
}
}

/**
* Prepare condition arguments from the different supported where styles
*
* @param mixed $condition
* @param array $args
*
* @return array
*/
protected function prepareConditionArguments($condition, array $args)
{
// Default operator
$operator = Sql::ALL;

if (! is_array($condition) && ! empty($args)) {
// Variadic
$condition = [(string) $condition => $args];
} else {
// Array or string format
$operator = array_shift($args) ?: $operator;
}

return [$condition, $operator];
}

/**
* Clone the properties provided by this trait
*
Expand Down
26 changes: 12 additions & 14 deletions src/WhereInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public function getWhere();
* Add a WHERE part of the query
*
* This method lets you specify the WHERE part of the query using one of the two following supported formats:
* * String format, e.g. 'id = 1'
* * Array format, e.g. ['id = ?' => 1, ...]
* * String format, e.g. 'id = 1', i.e. `where(string $condition [, mixed ...$args])`
* * Array format, e.g. ['id = ?' => 1, ...], i.e. `where(array $condition [, string $operator])`
*
* This method does NOT quote the columns you specify for the WHERE.
* If you allow user input here, you must protected yourself against SQL injection using
Expand All @@ -31,49 +31,47 @@ public function getWhere();
* the specified WHERE part using the AND operator.
*
* @param string|ExpressionInterface|Select|array $condition The WHERE condition
* @param string $operator The operator to combine multiple conditions with,
* if the condition is in the array format
* @param mixed $args If condition is a string, parameter values for placeholders in the condition can be passed.
* If condition is an array, the only argument that is allowed is the operator to use to combine
* these conditions. By default, this operator is {@link Sql::ALL} (AND)
*
* @return $this
*/
public function where($condition, $operator = Sql::ALL);
public function where($condition, ...$args);

/**
* Add a OR part to the WHERE part of the query
*
* Please see {@link where()} for the supported formats and restrictions regarding quoting of the field names.
*
* @param string|ExpressionInterface|Select|array $condition The WHERE condition
* @param string $operator The operator to combine multiple conditions with,
* if the condition is in the array format
* @param mixed ...$args Please see {@link where()} for details
*
* @return $this
*/
public function orWhere($condition, $operator = Sql::ALL);
public function orWhere($condition, ...$args);

/**
* Add a AND NOT part to the WHERE part of the query
*
* Please see {@link where()} for the supported formats and restrictions regarding quoting of the field names.
*
* @param string|ExpressionInterface|Select|array $condition The WHERE condition
* @param string $operator The operator to combine multiple conditions with,
* if the condition is in the array format
* @param mixed ...$args Please see {@link where()} for details
*
* @return $this
*/
public function notWhere($condition, $operator = Sql::ALL);
public function notWhere($condition, ...$args);

/**
* Add a OR NOT part to the WHERE part of the query
*
* Please see {@link where()} for the supported formats and restrictions regarding quoting of the field names.
*
* @param string|ExpressionInterface|Select|array $condition The WHERE condition
* @param string $operator The operator to combine multiple conditions with,
* if the condition is in the array format
* @param mixed ...$args Please see {@link where()} for details
*
* @return $this
*/
public function orNotWhere($condition, $operator = Sql::ALL);
public function orNotWhere($condition, ...$args);
}
18 changes: 18 additions & 0 deletions tests/ExpressionThatCanBeRenderedToString.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace ipl\Tests\Sql;

class ExpressionThatCanBeRenderedToString
{
protected $expression;

public function __construct($expression)
{
$this->expression = $expression;
}

public function __toString()
{
return $this->expression;
}
}
28 changes: 28 additions & 0 deletions tests/WhereTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ public function testSingleNotWhere()
$this->assertCorrectStatementAndValues('WHERE NOT (foo = bar)', []);
}

public function testVariadicWhereUsedVariadic()
{
$this->query->where('a IN (?) AND b < ?', [1, 2, 3], 4);
$this->assertCorrectStatementAndValues('WHERE a IN (?, ?, ?) AND b < ?', [1, 2, 3, 4]);
}

public function testNotWhereCombiningVariadicAndArrayStyle()
{
$this->query->where('a = ?', 1);
$this->query->notWhere('a IN (?) AND b < ?', [2, 3, 4], 5);
$this->query->notWhere(['a = ?' => 6, 'b = ?' => 7], Sql::ANY);
$this->assertCorrectStatementAndValues(
'WHERE ((a = ?) AND (NOT (a IN (?, ?, ?) AND b < ?))) AND (NOT ((a = ?) OR (b = ?)))',
[1, 2, 3, 4, 5, 6, 7]
);
}

public function testNotWhereArrayFormat()
{
$this->query->notWhere(['c1 = x']);
Expand Down Expand Up @@ -209,6 +226,17 @@ public function testWhereWithSelectAndExpression()
$this->assertCorrectStatementAndValues('WHERE EXISTS (SELECT 1 FROM t1 WHERE c2 = ? LIMIT 1)', [1]);
}

public function testWhereWithExpressionThatCanBeRenderedToString()
{
$this->query->where(
new ExpressionThatCanBeRenderedToString("COALESCE('a', ?) = ?"),
[1, 2],
1
);

$this->assertCorrectStatementAndValues("WHERE COALESCE('a', ?, ?) = ?", [1, 2, 1]);
}

public function testResetWhere()
{
$this->query->where('c1 = x');
Expand Down