Replaced func_get_args() with variadic arguments

parent 22854d27
# Upgrade to 3.0
## BC BREAK: Changes in the QueryBuilder API.
1. The `select()`, `addSelect()`, `groupBy()` and `addGroupBy()` methods no longer accept an array of arguments. Pass each expression as an individual argument or expand an array of expressions using the `...` operator.
2. The `select()`, `addSelect()`, `groupBy()` and `addGroupBy()` methods no longer ignore the first argument if it's empty.
3. The `addSelect()` method can be no longer called without arguments.
## BC BREAK: `QueryBuilder::insert()`, `update()` and `delete()` signatures changed
These methods now require the `$table` parameter, and do not support aliases anymore.
......
......@@ -5,9 +5,6 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Query\Expression;
use Doctrine\DBAL\Connection;
use function func_get_arg;
use function func_get_args;
use function func_num_args;
use function implode;
use function sprintf;
......@@ -41,7 +38,7 @@ class ExpressionBuilder
}
/**
* Creates a conjunction of the given boolean expressions.
* Creates a conjunction of the given expressions.
*
* Example:
*
......@@ -49,16 +46,15 @@ class ExpressionBuilder
* // (u.type = ?) AND (u.role = ?)
* $expr->andX('u.type = ?', 'u.role = ?'));
*
* @param mixed $x Optional clause. Defaults = null, but requires
* at least one defined when converting to string.
* @param string|CompositeExpression ...$expressions Requires at least one defined when converting to string.
*/
public function andX($x = null) : CompositeExpression
public function andX(...$expressions) : CompositeExpression
{
return new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args());
return new CompositeExpression(CompositeExpression::TYPE_AND, $expressions);
}
/**
* Creates a disjunction of the given boolean expressions.
* Creates a disjunction of the given expressions.
*
* Example:
*
......@@ -66,12 +62,11 @@ class ExpressionBuilder
* // (u.type = ?) OR (u.role = ?)
* $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?'));
*
* @param mixed $x Optional clause. Defaults = null, but requires
* at least one defined when converting to string.
* @param string|CompositeExpression ...$expressions Requires at least one defined when converting to string.
*/
public function orX($x = null) : CompositeExpression
public function orX(...$expressions) : CompositeExpression
{
return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args());
return new CompositeExpression(CompositeExpression::TYPE_OR, $expressions);
}
/**
......@@ -210,27 +205,27 @@ class ExpressionBuilder
}
/**
* Creates a LIKE() comparison expression with the given arguments.
* Creates a LIKE comparison expression.
*
* @param string $x Field in string format to be inspected by LIKE() comparison.
* @param mixed $y Argument to be used in LIKE() comparison.
*/
public function like(string $x, $y/*, ?string $escapeChar = null */) : string
public function like(string $x, $y, ?string $escapeChar = null) : string
{
return $this->comparison($x, 'LIKE', $y) .
(func_num_args() >= 3 ? sprintf(' ESCAPE %s', func_get_arg(2)) : '');
($escapeChar !== null ? sprintf(' ESCAPE %s', $escapeChar) : '');
}
/**
* Creates a NOT LIKE() comparison expression with the given arguments.
* Creates a NOT LIKE comparison expression
*
* @param string $x Field in string format to be inspected by NOT LIKE() comparison.
* @param mixed $y Argument to be used in NOT LIKE() comparison.
*/
public function notLike(string $x, $y/*, ?string $escapeChar = null */) : string
public function notLike(string $x, $y, ?string $escapeChar = null) : string
{
return $this->comparison($x, 'NOT LIKE', $y) .
(func_num_args() >= 3 ? sprintf(' ESCAPE %s', func_get_arg(2)) : '');
($escapeChar !== null ? sprintf(' ESCAPE %s', $escapeChar) : '');
}
/**
......
......@@ -13,9 +13,9 @@ use Doctrine\DBAL\Query\Expression\CompositeExpression;
use Doctrine\DBAL\Query\Expression\ExpressionBuilder;
use function array_key_exists;
use function array_keys;
use function array_unshift;
use function func_get_args;
use function func_num_args;
use function array_merge;
use function array_shift;
use function count;
use function implode;
use function is_array;
use function is_object;
......@@ -454,21 +454,19 @@ class QueryBuilder
* ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
* </code>
*
* @param mixed $select The selection expressions.
* @param string ...$expressions The selection expressions.
*
* @return $this This QueryBuilder instance.
*/
public function select($select = null) : self
public function select(string ...$expressions) : self
{
$this->type = self::SELECT;
if (empty($select)) {
if (count($expressions) < 1) {
return $this;
}
$selects = is_array($select) ? $select : func_get_args();
return $this->add('select', $selects);
return $this->add('select', $expressions);
}
/**
......@@ -501,21 +499,16 @@ class QueryBuilder
* ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
* </code>
*
* @param mixed $select The selection expression.
* @param string $expression The selection expression.
* @param string ...$expressions Additional selection expressions.
*
* @return $this This QueryBuilder instance.
*/
public function addSelect($select = null) : self
public function addSelect(string $expression, string ...$expressions) : self
{
$this->type = self::SELECT;
if (empty($select)) {
return $this;
}
$selects = is_array($select) ? $select : func_get_args();
return $this->add('select', $selects, true);
return $this->add('select', array_merge([$expression], $expressions), true);
}
/**
......@@ -744,17 +737,14 @@ class QueryBuilder
* ->where($or);
* </code>
*
* @param mixed $predicates The restriction predicates.
* @param string|CompositeExpression $predicate The WHERE clause predicate.
* @param string|CompositeExpression ...$predicates Additional WHERE clause predicates.
*
* @return $this This QueryBuilder instance.
*/
public function where($predicates)
public function where($predicate, ...$predicates)
{
if (! (func_num_args() === 1 && $predicates instanceof CompositeExpression)) {
$predicates = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args());
}
return $this->add('where', $predicates);
return $this->setPredicates('where', $predicate, ...$predicates);
}
/**
......@@ -771,23 +761,14 @@ class QueryBuilder
*
* @see where()
*
* @param mixed $where The query restrictions.
* @param string|CompositeExpression $predicate The predicate to append.
* @param string|CompositeExpression ...$predicates Additional predicates to append.
*
* @return $this This QueryBuilder instance.
*/
public function andWhere($where)
public function andWhere($predicate, ...$predicates)
{
$args = func_get_args();
$where = $this->getQueryPart('where');
if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) {
$where->addMultiple($args);
} else {
array_unshift($args, $where);
$where = new CompositeExpression(CompositeExpression::TYPE_AND, $args);
}
return $this->add('where', $where, true);
return $this->appendPredicates('where', CompositeExpression::TYPE_AND, $predicate, ...$predicates);
}
/**
......@@ -804,27 +785,18 @@ class QueryBuilder
*
* @see where()
*
* @param mixed $where The WHERE statement.
* @param string|CompositeExpression $predicate The predicate to append.
* @param string|CompositeExpression ...$predicates Additional predicates to append.
*
* @return $this This QueryBuilder instance.
*/
public function orWhere($where)
public function orWhere($predicate, ...$predicates)
{
$args = func_get_args();
$where = $this->getQueryPart('where');
if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) {
$where->addMultiple($args);
} else {
array_unshift($args, $where);
$where = new CompositeExpression(CompositeExpression::TYPE_OR, $args);
}
return $this->add('where', $where, true);
return $this->appendPredicates('where', CompositeExpression::TYPE_OR, $predicate, ...$predicates);
}
/**
* Specifies a grouping over the results of the query.
* Specifies one or more grouping expressions over the results of the query.
* Replaces any previously specified groupings, if any.
*
* <code>
......@@ -834,23 +806,18 @@ class QueryBuilder
* ->groupBy('u.id');
* </code>
*
* @param mixed $groupBy The grouping expression.
* @param string $expression The grouping expression
* @param string ...$expressions Additional grouping expressions
*
* @return $this This QueryBuilder instance.
*/
public function groupBy($groupBy) : self
public function groupBy(string $expression, string ...$expressions) : self
{
if (empty($groupBy)) {
return $this;
}
$groupBy = is_array($groupBy) ? $groupBy : func_get_args();
return $this->add('groupBy', $groupBy, false);
return $this->add('groupBy', array_merge([$expression], $expressions), false);
}
/**
* Adds a grouping expression to the query.
* Adds one or more grouping expressions to the query.
*
* <code>
* $qb = $conn->createQueryBuilder()
......@@ -860,19 +827,14 @@ class QueryBuilder
* ->addGroupBy('u.createdAt');
* </code>
*
* @param mixed $groupBy The grouping expression.
* @param string $expression The grouping expression
* @param string ...$expressions Additional grouping expressions
*
* @return $this This QueryBuilder instance.
*/
public function addGroupBy($groupBy) : self
public function addGroupBy(string $expression, string ...$expressions) : self
{
if (empty($groupBy)) {
return $this;
}
$groupBy = is_array($groupBy) ? $groupBy : func_get_args();
return $this->add('groupBy', $groupBy, true);
return $this->add('groupBy', array_merge([$expression], $expressions), true);
}
/**
......@@ -929,63 +891,87 @@ class QueryBuilder
* Specifies a restriction over the groups of the query.
* Replaces any previous having restrictions, if any.
*
* @param mixed $having The restriction over the groups.
* @param string|CompositeExpression $predicate The HAVING clause predicate.
* @param string|CompositeExpression ...$predicates Additional HAVING clause predicates.
*
* @return $this This QueryBuilder instance.
*/
public function having($having)
public function having($predicate, ...$predicates)
{
if (! (func_num_args() === 1 && $having instanceof CompositeExpression)) {
$having = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args());
}
return $this->add('having', $having);
return $this->setPredicates('having', $predicate, ...$predicates);
}
/**
* Adds a restriction over the groups of the query, forming a logical
* conjunction with any existing having restrictions.
*
* @param mixed $having The restriction to append.
* @param string|CompositeExpression $predicate The predicate to append.
* @param string|CompositeExpression ...$predicates Additional predicates to append.
*
* @return $this This QueryBuilder instance.
*/
public function andHaving($having)
public function andHaving($predicate, ...$predicates)
{
$args = func_get_args();
$having = $this->getQueryPart('having');
return $this->appendPredicates('having', CompositeExpression::TYPE_AND, $predicate, ...$predicates);
}
if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) {
$having->addMultiple($args);
/**
* Adds a restriction over the groups of the query, forming a logical
* disjunction with any existing having restrictions.
*
* @param string|CompositeExpression $predicate The predicate to append.
* @param string|CompositeExpression ...$predicates Additional predicates to append.
*
* @return $this This QueryBuilder instance.
*/
public function orHaving($predicate, ...$predicates)
{
return $this->appendPredicates('having', CompositeExpression::TYPE_OR, $predicate, ...$predicates);
}
/**
* Sets one or more predicates combined by the AND logic as the given query clause.
* Replaces any previously specified predicates.
*
* @param string|CompositeExpression ...$predicates
*
* @return $this This QueryBuilder instance.
*/
private function setPredicates(string $clause, ...$predicates) : self
{
if (count($predicates) > 1) {
$predicate = new CompositeExpression(
CompositeExpression::TYPE_AND,
$predicates
);
} else {
array_unshift($args, $having);
$having = new CompositeExpression(CompositeExpression::TYPE_AND, $args);
$predicate = array_shift($predicates);
}
return $this->add('having', $having);
return $this->add($clause, $predicate);
}
/**
* Adds a restriction over the groups of the query, forming a logical
* disjunction with any existing having restrictions.
* Appends the given predicates combined by the given type of logic to the given query clause.
*
* @param mixed $having The restriction to add.
* @param string|CompositeExpression ...$predicates
*
* @return $this This QueryBuilder instance.
*/
public function orHaving($having)
private function appendPredicates(string $clause, string $type, ...$predicates) : self
{
$args = func_get_args();
$having = $this->getQueryPart('having');
$predicate = $this->getQueryPart($clause);
if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) {
$having->addMultiple($args);
if ($predicate instanceof CompositeExpression && $predicate->getType() === $type) {
$predicate->addMultiple($predicates);
} else {
array_unshift($args, $having);
$having = new CompositeExpression(CompositeExpression::TYPE_OR, $args);
$predicate = new CompositeExpression(
$type,
array_merge([$predicate], $predicates)
);
}
return $this->add('having', $having);
return $this->add($clause, $predicate, true);
}
/**
......
......@@ -20,11 +20,8 @@ use function array_map;
use function array_shift;
use function array_values;
use function assert;
use function call_user_func_array;
use function count;
use function func_get_args;
use function is_array;
use function is_callable;
use function preg_match;
use function strtolower;
......@@ -75,20 +72,14 @@ abstract class AbstractSchemaManager
* $result = $sm->tryMethod('dropView', 'view_name');
* </code>
*
* @param mixed ...$arguments
*
* @return mixed
*/
public function tryMethod()
public function tryMethod(string $method, ...$arguments)
{
$args = func_get_args();
$method = $args[0];
unset($args[0]);
$args = array_values($args);
$callback = [$this, $method];
assert(is_callable($callback));
try {
return call_user_func_array($callback, $args);
return $this->$method(...$arguments);
} catch (Throwable $e) {
return false;
}
......
......@@ -36,8 +36,8 @@ class OracleSchemaManagerTest extends SchemaManagerFunctionalTestCase
public function testRenameTable() : void
{
$this->schemaManager->tryMethod('DropTable', 'list_tables_test');
$this->schemaManager->tryMethod('DropTable', 'list_tables_test_new_name');
$this->schemaManager->tryMethod('dropTable', 'list_tables_test');
$this->schemaManager->tryMethod('dropTable', 'list_tables_test_new_name');
$this->createTestTable('list_tables_test');
$this->schemaManager->renameTable('list_tables_test', 'list_tables_test_new_name');
......
......@@ -125,8 +125,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectWithAndWhereConditions() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -138,8 +137,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectWithOrWhereConditions() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -151,8 +149,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectWithOrOrWhereConditions() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -164,8 +161,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectWithAndOrWhereConditions() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -179,8 +175,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectGroupBy() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -189,34 +184,9 @@ class QueryBuilderTest extends DbalTestCase
self::assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id', (string) $qb);
}
public function testSelectEmptyGroupBy() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->groupBy([])
->from('users', 'u');
self::assertEquals('SELECT u.*, p.* FROM users u', (string) $qb);
}
public function testSelectEmptyAddGroupBy() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->addGroupBy([])
->from('users', 'u');
self::assertEquals('SELECT u.*, p.* FROM users u', (string) $qb);
}
public function testSelectAddGroupBy() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -228,8 +198,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectAddGroupBys() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -241,8 +210,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectHaving() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -254,8 +222,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectAndHaving() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -267,8 +234,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectHavingAndHaving() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -281,8 +247,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectHavingOrHaving() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -295,8 +260,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectOrHavingOrHaving() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -309,8 +273,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectHavingAndOrHaving() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -324,8 +287,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectOrderBy() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -336,8 +298,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectAddOrderBy() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -349,8 +310,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectAddAddOrderBy() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*', 'p.*')
->from('users', 'u')
......@@ -371,8 +331,7 @@ class QueryBuilderTest extends DbalTestCase
public function testSelectAddSelect() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*')
->addSelect('p.*')
......@@ -381,19 +340,9 @@ class QueryBuilderTest extends DbalTestCase
self::assertEquals('SELECT u.*, p.* FROM users u', (string) $qb);
}
public function testEmptyAddSelect() : void
{
$qb = new QueryBuilder($this->conn);
$qb2 = $qb->addSelect();
self::assertSame($qb, $qb2);
self::assertEquals(QueryBuilder::SELECT, $qb->getType());
}
public function testSelectMultipleFrom() : void
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb = new QueryBuilder($this->conn);
$qb->select('u.*')
->addSelect('p.*')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment