0 follower

Abstract Class Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder

InheritanceYiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
ImplementsYiisoft\Db\QueryBuilder\DQLQueryBuilderInterface

It's used to query data from a database.

Public Methods

Hide inherited methods

Method Description Defined By
__construct() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
build() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildColumns() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildCondition() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildExpression() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildFor() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildFrom() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildGroupBy() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildHaving() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildJoin() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildLimit() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildOrderBy() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildOrderByAndLimit() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildSelect() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildUnion() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildWhere() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
buildWithQueries() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
createConditionFromArray() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
getExpressionBuilder() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
selectExists() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
setConditionClasses() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
setExpressionBuilders() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
setSeparator() Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder

Protected Methods

Hide inherited methods

Method Description Defined By
defaultConditionClasses() Has an array of default condition classes. Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
defaultExpressionBuilders() Has an array of default expression builders. Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder
extractAlias() Extracts table alias if there is one or returns false. Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder

Property Details

Hide inherited properties

$conditionClasses protected property

Map of condition aliases to condition classes. For example:

return [
    'LIKE' => \Yiisoft\Db\QueryBuilder\Condition\Like::class,
];

This property is used by {@see \Yiisoft\Db\QueryBuilder\createConditionFromArray} method.

See default condition classes list in {@see \Yiisoft\Db\QueryBuilder\defaultConditionClasses()} method.

In case you want to add custom conditions support, use the {@see \Yiisoft\Db\QueryBuilder\setConditionClasses()} method.

See also:

protected array $conditionClasses = []
$expressionBuilders protected property

Map of expression aliases to expression classes.

For example:

[
   Expression::class => ExpressionBuilder::class
]

This property is mainly used by {@see \Yiisoft\Db\QueryBuilder\buildExpression()} to build SQL expressions form expression objects. See default values in {@see \Yiisoft\Db\QueryBuilder\defaultExpressionBuilders()} method.

{@see \Yiisoft\Db\QueryBuilder\setExpressionBuilders()} {@see \Yiisoft\Db\QueryBuilder\defaultExpressionBuilders()}

protected array $expressionBuilders = []
$queryBuilder protected property
$separator protected property
protected string $separator ' '

Method Details

Hide inherited methods

__construct() public method

public mixed __construct ( Yiisoft\Db\QueryBuilder\QueryBuilderInterface $queryBuilder, Yiisoft\Db\Schema\QuoterInterface $quoter )
$queryBuilder Yiisoft\Db\QueryBuilder\QueryBuilderInterface
$quoter Yiisoft\Db\Schema\QuoterInterface

                public function __construct(
    protected QueryBuilderInterface $queryBuilder,
    private QuoterInterface $quoter,
) {
    $this->expressionBuilders = $this->defaultExpressionBuilders();
    $this->conditionClasses = $this->defaultConditionClasses();
}

            
build() public method

public array build ( Yiisoft\Db\Query\QueryInterface $query, array $params = [] )
$query Yiisoft\Db\Query\QueryInterface
$params array

                public function build(QueryInterface $query, array $params = []): array
{
    $query = $query->prepare($this->queryBuilder);
    $params = empty($params) ? $query->getParams() : array_merge($params, $query->getParams());
    $clauses = [
        $this->buildSelect($query->getSelect(), $params, $query->getDistinct(), $query->getSelectOption()),
        $this->buildFrom($query->getFrom(), $params),
        $this->buildJoin($query->getJoins(), $params),
        $this->buildWhere($query->getWhere(), $params),
        $this->buildGroupBy($query->getGroupBy(), $params),
        $this->buildHaving($query->getHaving(), $params),
    ];
    $sql = implode($this->separator, array_filter($clauses));
    $sql = $this->buildOrderByAndLimit($sql, $query->getOrderBy(), $query->getLimit(), $query->getOffset(), $params);
    $for = $this->buildFor($query->getFor());
    if ($for !== '') {
        $sql .= $this->separator . $for;
    }
    $union = $this->buildUnion($query->getUnions(), $params);
    if ($union !== '') {
        $sql = "($sql)$this->separator$union";
    }
    $with = $this->buildWithQueries($query->getWithQueries(), $params);
    if ($with !== '') {
        $sql = "$with$this->separator$sql";
    }
    return [$sql, $params];
}

            
buildColumns() public method

public string buildColumns ( array|string $columns )
$columns array|string

                public function buildColumns(array|string $columns): string
{
    if (!is_array($columns)) {
        if (str_contains($columns, '(')) {
            return $columns;
        }
        /** @var list<string> We use valid regular expressions, so the result is always a list of strings */
        $columns = preg_split('/\s*,\s*/', $columns, -1, PREG_SPLIT_NO_EMPTY);
    }
    $columns = array_map(
        fn(string|ExpressionInterface $column): string => $column instanceof ExpressionInterface
            ? $this->buildExpression($column)
            : $this->quoter->quoteColumnName($column),
        $columns,
    );
    return implode(', ', $columns);
}

            
buildCondition() public method

public string buildCondition ( array|string|Yiisoft\Db\Expression\ExpressionInterface|null $condition, array &$params = [] )
$condition array|string|Yiisoft\Db\Expression\ExpressionInterface|null
$params array

                public function buildCondition(array|string|ExpressionInterface|null $condition, array &$params = []): string
{
    if (empty($condition)) {
        if ($condition === '0') {
            return '0';
        }
        return '';
    }
    if (is_array($condition)) {
        $condition = $this->createConditionFromArray($condition);
    } elseif (is_string($condition)) {
        $condition = new Expression($condition, $params);
        $params = [];
    }
    return $this->buildExpression($condition, $params);
}

            
buildExpression() public method

public string buildExpression ( Yiisoft\Db\Expression\ExpressionInterface $expression, array &$params = [] )
$expression Yiisoft\Db\Expression\ExpressionInterface
$params array

                public function buildExpression(ExpressionInterface $expression, array &$params = []): string
{
    return $this->queryBuilder
        ->getExpressionBuilder($expression)
        ->build($expression, $params);
}

            
buildFor() public method

public string buildFor ( array $values )
$values array

                public function buildFor(array $values): string
{
    if (empty($values)) {
        return '';
    }
    return 'FOR ' . implode($this->separator . 'FOR ', $values);
}

            
buildFrom() public method

public string buildFrom ( array $tables, array &$params )
$tables array
$params array

                public function buildFrom(array $tables, array &$params): string
{
    if (empty($tables)) {
        return '';
    }
    /** @var string[] $tables */
    $tables = $this->quoteTableNames($tables, $params);
    return 'FROM ' . implode(', ', $tables);
}

            
buildGroupBy() public method

public string buildGroupBy ( array $columns, array &$params = [] )
$columns array
$params array

                public function buildGroupBy(array $columns, array &$params = []): string
{
    if (empty($columns)) {
        return '';
    }
    /** @psalm-var array<string, ExpressionInterface|string> $columns */
    foreach ($columns as $i => $column) {
        if ($column instanceof ExpressionInterface) {
            $columns[$i] = $this->buildExpression($column, $params);
        } elseif (!str_contains($column, '(')) {
            $columns[$i] = $this->quoter->quoteColumnName($column);
        }
    }
    /** @psalm-var array<string, Expression|string> $columns */
    return 'GROUP BY ' . implode(', ', $columns);
}

            
buildHaving() public method

public string buildHaving ( array|Yiisoft\Db\Expression\ExpressionInterface|string|null $condition, array &$params = [] )
$condition array|Yiisoft\Db\Expression\ExpressionInterface|string|null
$params array

                public function buildHaving(array|ExpressionInterface|string|null $condition, array &$params = []): string
{
    $having = $this->buildCondition($condition, $params);
    return ($having === '') ? '' : ('HAVING ' . $having);
}

            
buildJoin() public method

public string buildJoin ( array $joins, array &$params )
$joins array
$params array

                public function buildJoin(array $joins, array &$params): string
{
    if (empty($joins)) {
        return '';
    }
    foreach ($joins as $i => $join) {
        /** @psalm-suppress DocblockTypeContradiction */
        if (!is_array($join) || !isset($join[0], $join[1])) {
            throw new InvalidArgumentException(
                'A join clause must be specified as an array of join type, join table, and optionally join condition.',
            );
        }
        [$joinType, $table] = $join;
        $tables = $this->quoteTableNames(is_array($table) ? $table : [$table], $params);
        $table = reset($tables);
        $joins[$i] = "$joinType $table";
        if (isset($join[2])) {
            if (is_array($join[2]) && !isset($join[2][0])) {
                foreach ($join[2] as &$column) {
                    if (is_string($column)) {
                        $column = new ColumnName($column);
                    }
                }
                unset($column);
            }
            $condition = $this->buildCondition($join[2], $params);
            if ($condition !== '') {
                $joins[$i] .= ' ON ' . $condition;
            }
        }
    }
    /** @psalm-var array<string> $joins */
    return implode($this->separator, $joins);
}

            
buildLimit() public method

public string buildLimit ( Yiisoft\Db\Expression\ExpressionInterface|integer|null $limit, Yiisoft\Db\Expression\ExpressionInterface|integer|null $offset )
$limit Yiisoft\Db\Expression\ExpressionInterface|integer|null
$offset Yiisoft\Db\Expression\ExpressionInterface|integer|null

                public function buildLimit(ExpressionInterface|int|null $limit, ExpressionInterface|int|null $offset): string
{
    $sql = '';
    if ($limit !== null) {
        $sql = 'LIMIT '
            . ($limit instanceof ExpressionInterface ? $this->buildExpression($limit) : (string) $limit);
    }
    if (!empty($offset)) {
        $sql .= ' OFFSET '
            . ($offset instanceof ExpressionInterface ? $this->buildExpression($offset) : (string) $offset);
    }
    return ltrim($sql);
}

            
buildOrderBy() public method

public string buildOrderBy ( array $columns, array &$params = [] )
$columns array
$params array

                public function buildOrderBy(array $columns, array &$params = []): string
{
    if (empty($columns)) {
        return '';
    }
    $orders = [];
    /** @psalm-var array<string, ExpressionInterface|int|string> $columns */
    foreach ($columns as $name => $direction) {
        if ($direction instanceof ExpressionInterface) {
            $orders[] = $this->buildExpression($direction, $params);
        } else {
            $orders[] = $this->quoter->quoteColumnName($name) . ($direction === SORT_DESC ? ' DESC' : '');
        }
    }
    return 'ORDER BY ' . implode(', ', $orders);
}

            
buildOrderByAndLimit() public method

public string buildOrderByAndLimit ( string $sql, array $orderBy, Yiisoft\Db\Expression\ExpressionInterface|integer|null $limit, Yiisoft\Db\Expression\ExpressionInterface|integer|null $offset, array &$params = [] )
$sql string
$orderBy array
$limit Yiisoft\Db\Expression\ExpressionInterface|integer|null
$offset Yiisoft\Db\Expression\ExpressionInterface|integer|null
$params array

                public function buildOrderByAndLimit(
    string $sql,
    array $orderBy,
    ExpressionInterface|int|null $limit,
    ExpressionInterface|int|null $offset,
    array &$params = [],
): string {
    $orderBy = $this->buildOrderBy($orderBy, $params);
    if ($orderBy !== '') {
        $sql .= $this->separator . $orderBy;
    }
    $limit = $this->buildLimit($limit, $offset);
    if ($limit !== '') {
        $sql .= $this->separator . $limit;
    }
    return $sql;
}

            
buildSelect() public method

public string buildSelect ( array $columns, array &$params, boolean $distinct false, string|null $selectOption null )
$columns array
$params array
$distinct boolean
$selectOption string|null

                public function buildSelect(
    array $columns,
    array &$params,
    bool $distinct = false,
    ?string $selectOption = null,
): string {
    $select = $distinct ? 'SELECT DISTINCT' : 'SELECT';
    if ($selectOption !== null) {
        $select .= ' ' . $selectOption;
    }
    if (empty($columns)) {
        return $select . ' *';
    }
    $quoter = $this->quoter;
    foreach ($columns as $i => $column) {
        $isIndexString = is_string($i);
        if (!is_string($column)) {
            $columns[$i] = $this->queryBuilder->buildValue($column, $params);
        } elseif (!str_contains($column, '(')) {
            if (!$isIndexString
                && preg_match('/^(.*?)(?i:\s+as\s+|\s+)([\w\-_.]+)$/', $column, $matches) === 1
            ) {
                $columns[$i] = $quoter->quoteColumnName($matches[1])
                    . ' AS ' . $quoter->quoteSimpleColumnName($matches[2]);
                continue;
            }
            $columns[$i] = $quoter->quoteColumnName($column);
        }
        if ($isIndexString && $i !== $column) {
            /**
             * @var string $i
             * @psalm-var string $columns[$i]
             */
            $columns[$i] .= ' AS ' . $quoter->quoteColumnName($i);
        }
    }
    /** @psalm-var array<string, Expression|string> $columns */
    return $select . ' ' . implode(', ', $columns);
}

            
buildUnion() public method

public string buildUnion ( array $unions, array &$params )
$unions array
$params array

                public function buildUnion(array $unions, array &$params): string
{
    if (empty($unions)) {
        return '';
    }
    $result = '';
    /** @psalm-var array<array{query:string|Query, all:bool}> $unions */
    foreach ($unions as $union) {
        if ($union['query'] instanceof QueryInterface) {
            [$union['query'], $params] = $this->build($union['query'], $params);
        }
        $result .= 'UNION ' . ($union['all'] ? 'ALL ' : '') . '( ' . $union['query'] . ' ) ';
    }
    return trim($result);
}

            
buildWhere() public method

public string buildWhere ( array|string|Yiisoft\Db\QueryBuilder\Condition\ConditionInterface|Yiisoft\Db\Expression\ExpressionInterface|null $condition, array &$params = [] )
$condition array|string|Yiisoft\Db\QueryBuilder\Condition\ConditionInterface|Yiisoft\Db\Expression\ExpressionInterface|null
$params array

                public function buildWhere(
    array|string|ConditionInterface|ExpressionInterface|null $condition,
    array &$params = [],
): string {
    $where = $this->buildCondition($condition, $params);
    return ($where === '') ? '' : ('WHERE ' . $where);
}

            
buildWithQueries() public method

public string buildWithQueries ( array $withQueries, array &$params )
$withQueries array
$params array

                public function buildWithQueries(array $withQueries, array &$params): string
{
    if (empty($withQueries)) {
        return '';
    }
    $recursive = false;
    $result = [];
    foreach ($withQueries as $withQuery) {
        if ($withQuery->recursive) {
            $recursive = true;
        }
        if ($withQuery->query instanceof QueryInterface) {
            [$querySql, $params] = $this->build($withQuery->query, $params);
        } else {
            $querySql = $withQuery->query;
        }
        $quotedAlias = $this->quoteCteAlias($withQuery->alias);
        $result[] = $quotedAlias . ' AS (' . $querySql . ')';
    }
    return 'WITH ' . ($recursive ? 'RECURSIVE ' : '') . implode(', ', $result);
}

            
createConditionFromArray() public method

public Yiisoft\Db\QueryBuilder\Condition\ConditionInterface createConditionFromArray ( array $condition )
$condition array

                public function createConditionFromArray(array $condition): ConditionInterface
{
    /** operator format: operator, operand 1, operand 2, ... */
    if (isset($condition[0])) {
        $operator = strtoupper((string) array_shift($condition));
        $className = $this->conditionClasses[$operator] ?? Simple::class;
        return $className::fromArrayDefinition($operator, $condition);
    }
    $conditions = [];
    foreach ($condition as $column => $value) {
        if (!is_string($column)) {
            throw new InvalidArgumentException('Condition array must have string keys.');
        }
        if (is_iterable($value) || $value instanceof QueryInterface) {
            $conditions[] = new Condition\In($column, $value);
            continue;
        }
        $conditions[] = new Condition\Equals($column, $value);
    }
    return count($conditions) === 1 ? $conditions[0] : new Condition\AndX(...$conditions);
}

            
defaultConditionClasses() protected method

Has an array of default condition classes.

Extend this method if you want to change default condition classes for the query builder.

See {@see \Yiisoft\Db\QueryBuilder\conditionClasses} docs for details.

protected array defaultConditionClasses ( )

                protected function defaultConditionClasses(): array
{
    return [
        'NOT' => Condition\Not::class,
        'AND' => Condition\AndX::class,
        'OR' => Condition\OrX::class,
        '=' => Condition\Equals::class,
        '!=' => Condition\NotEquals::class,
        '<>' => Condition\NotEquals::class,
        '>' => Condition\GreaterThan::class,
        '>=' => Condition\GreaterThanOrEqual::class,
        '<' => Condition\LessThan::class,
        '<=' => Condition\LessThanOrEqual::class,
        'BETWEEN' => Condition\Between::class,
        'NOT BETWEEN' => Condition\NotBetween::class,
        'IN' => Condition\In::class,
        'NOT IN' => Condition\NotIn::class,
        'LIKE' => Condition\Like::class,
        'NOT LIKE' => Condition\NotLike::class,
        'EXISTS' => Condition\Exists::class,
        'NOT EXISTS' => Condition\NotExists::class,
        'ARRAY OVERLAPS' => Condition\ArrayOverlaps::class,
        'JSON OVERLAPS' => Condition\JsonOverlaps::class,
    ];
}

            
defaultExpressionBuilders() protected method

Has an array of default expression builders.

Extend this method and override it if you want to change default expression builders for this query builder.

See {@see \Yiisoft\Db\QueryBuilder\expressionBuilders} docs for details.

protected array defaultExpressionBuilders ( )

                protected function defaultExpressionBuilders(): array
{
    return [
        Query::class => QueryExpressionBuilder::class,
        Param::class => ParamBuilder::class,
        Expression::class => ExpressionBuilder::class,
        CompositeExpression::class => CompositeExpressionBuilder::class,
        Condition\Not::class => Condition\Builder\NotBuilder::class,
        Condition\AndX::class => Condition\Builder\LogicalBuilder::class,
        Condition\OrX::class => Condition\Builder\LogicalBuilder::class,
        Condition\Between::class => Condition\Builder\BetweenBuilder::class,
        Condition\NotBetween::class => Condition\Builder\BetweenBuilder::class,
        Condition\In::class => Condition\Builder\InBuilder::class,
        Condition\NotIn::class => Condition\Builder\InBuilder::class,
        Condition\Like::class => Condition\Builder\LikeBuilder::class,
        Condition\NotLike::class => Condition\Builder\LikeBuilder::class,
        Condition\Equals::class => Condition\Builder\CompareBuilder::class,
        Condition\NotEquals::class => Condition\Builder\CompareBuilder::class,
        Condition\GreaterThan::class => Condition\Builder\CompareBuilder::class,
        Condition\GreaterThanOrEqual::class => Condition\Builder\CompareBuilder::class,
        Condition\LessThan::class => Condition\Builder\CompareBuilder::class,
        Condition\LessThanOrEqual::class => Condition\Builder\CompareBuilder::class,
        Condition\Exists::class => Condition\Builder\ExistsBuilder::class,
        Condition\NotExists::class => Condition\Builder\ExistsBuilder::class,
        Condition\All::class => Condition\Builder\AllBuilder::class,
        Condition\None::class => Condition\Builder\NoneBuilder::class,
        Simple::class => Condition\Builder\SimpleBuilder::class,
        JsonValue::class => JsonValueBuilder::class,
        ArrayValue::class => ArrayValueBuilder::class,
        StructuredValue::class => StructuredValueBuilder::class,
        CaseX::class => CaseXBuilder::class,
        ColumnName::class => ColumnNameBuilder::class,
        Value::class => ValueBuilder::class,
        DateTimeValue::class => DateTimeValueBuilder::class,
        Length::class => LengthBuilder::class,
        Greatest::class => GreatestBuilder::class,
        Least::class => LeastBuilder::class,
        Longest::class => LongestBuilder::class,
        Shortest::class => ShortestBuilder::class,
    ];
}

            
extractAlias() protected method

Extracts table alias if there is one or returns false.

protected array|boolean extractAlias ( string $table )
$table string

                protected function extractAlias(string $table): array|bool
{
    if (preg_match('/^(.*?)(?i:\s+as|)\s+([^ ]+)$/', $table, $matches)) {
        return $matches;
    }
    return false;
}

            
getExpressionBuilder() public method

public Yiisoft\Db\Expression\ExpressionBuilderInterface getExpressionBuilder ( Yiisoft\Db\Expression\ExpressionInterface $expression )
$expression Yiisoft\Db\Expression\ExpressionInterface

                public function getExpressionBuilder(ExpressionInterface $expression): ExpressionBuilderInterface
{
    $className = $expression::class;
    if (!isset($this->expressionBuilders[$className])) {
        throw new NotSupportedException(
            'Expression of class ' . $className . ' can not be built in ' . static::class,
        );
    }
    return new $this->expressionBuilders[$className]($this->queryBuilder);
}

            
selectExists() public method

public string selectExists ( string $rawSql )
$rawSql string

                public function selectExists(string $rawSql): string
{
    return 'SELECT EXISTS(' . $rawSql . ') AS ' . $this->quoter->quoteSimpleColumnName('0');
}

            
setConditionClasses() public method

public void setConditionClasses ( array $classes )
$classes array

                public function setConditionClasses(array $classes): void
{
    $this->conditionClasses = array_merge($this->conditionClasses, $classes);
}

            
setExpressionBuilders() public method

public void setExpressionBuilders ( array $builders )
$builders array

                public function setExpressionBuilders(array $builders): void
{
    $this->expressionBuilders = array_merge($this->expressionBuilders, $builders);
}

            
setSeparator() public method

public void setSeparator ( string $separator )
$separator string

The separator between different fragments of an SQL statement.

Defaults to an empty space. This is mainly used by {@see \Yiisoft\Db\QueryBuilder\build()} when generating a SQL statement.

                public function setSeparator(string $separator): void
{
    $this->separator = $separator;
}