CoolCMS API

OrderByHelper
in package

Table of Contents

Constants

CURRENT_PRICE_PATTERN  : string = '/^currentPrice\[currencyId:(\d+)(?:,userGroupI...
Sort key for the current price in a currency: `currentPrice[currencyId:3]` or `currentPrice[currencyId:3,userGroupId:1]`.
LANGUAGE_SCOPED_PATTERN  : string = '/^([A-Za-z_][A-Za-z0-9_]*)\[languageId:(\d+)\]...
Sort key for a translation field in one language: `translations[languageId:2].name`.

Methods

addOrderBys()  : void
currentPriceField()  : string
Builds the sort key for the current product set price in the display currency.
parseCurrentPriceField()  : array{currencyId: int, userGroupId: ?int}|null
translatedField()  : string
Builds the sort key for a translated field in one language (e.g. the name in the page language).
withIdTiebreak()  : array<string, bool>
Appends a unique tiebreak key (id) to the ordering unless it is already present.
extractFieldName()  : string
joinLanguageScoped()  : string
Adds `LEFT JOIN root.relation alias WITH alias.languageId = N` and returns its alias.
parseOrderByField()  : array{type: "expression", field: string, path: string, expr: string}|array{type: "relation"|"simple", field: string, path: string, expr: null}

Constants

CURRENT_PRICE_PATTERN

Sort key for the current price in a currency: `currentPrice[currencyId:3]` or `currentPrice[currencyId:3,userGroupId:1]`.

private string CURRENT_PRICE_PATTERN = '/^currentPrice\[currencyId:(\d+)(?:,userGroupId:(\d+))?\]$/'

LANGUAGE_SCOPED_PATTERN

Sort key for a translation field in one language: `translations[languageId:2].name`.

private string LANGUAGE_SCOPED_PATTERN = '/^([A-Za-z_][A-Za-z0-9_]*)\[languageId:(\d+)\]\.([A-Za-z_][A-Za-z0-9_]*)$/'

Methods

addOrderBys()

public static addOrderBys(QueryBuilder $qb, array<string|int, mixed> $orderBys, string $fromTableAlias[, string|null $textTableAlias = null ]) : void
Parameters
$qb : QueryBuilder
$orderBys : array<string|int, mixed>
$fromTableAlias : string
$textTableAlias : string|null = null

currentPriceField()

Builds the sort key for the current product set price in the display currency.

public static currentPriceField(int $currencyId[, int|null $userGroupId = null ]) : string

IMPORTANT: the denormalized product_sets.price holds the price in the default currency only, so sorting by it on a page in another currency would order by the wrong amounts. The eshop Api repository (ProductSetRepository::applyOrdering()) turns this key into a subquery over the current-price view; the Api manager supplies the default price group, the front end does not know it.

Parameters
$currencyId : int
$userGroupId : int|null = null
Return values
string

parseCurrentPriceField()

public static parseCurrentPriceField(string $field) : array{currencyId: int, userGroupId: ?int}|null
Parameters
$field : string
Return values
array{currencyId: int, userGroupId: ?int}|null

translatedField()

Builds the sort key for a translated field in one language (e.g. the name in the page language).

public static translatedField(string $relation, string $field, int|null $languageId) : string

IMPORTANT: a bare translations.name joins translations of all languages, so SELECT DISTINCT id ... ORDER BY t.name sorts by the name in any of them, depending on which row the database picks. addOrderBys() turns this key into a LEFT JOIN ... WITH language = :id used for sorting only: nothing is filtered out (an entity without a translation sorts among nulls), at most one row per entity, and translation hydration is not affected.

A null language keeps the bare behavior (translations.name).

Parameters
$relation : string
$field : string
$languageId : int|null
Return values
string

withIdTiebreak()

Appends a unique tiebreak key (id) to the ordering unless it is already present.

public static withIdTiebreak(array<string, bool> $orderBys[, string $idField = 'id' ]) : array<string, bool>

IMPORTANT: without it, rows with equal sort values (price 0, same date, same view count) are ordered non-deterministically in MySQL/MariaDB, so LIMIT/OFFSET repeats some items across pages and skips others.

The id direction copies the direction of the last key (descending order puts newer ids first). An empty ordering stays empty: the caller wants no ordering (e.g. Elasticsearch relevance).

Parameters
$orderBys : array<string, bool>

field => ascending (true) / descending (false)

$idField : string = 'id'
Return values
array<string, bool>

extractFieldName()

private static extractFieldName(string $path) : string
Parameters
$path : string
Return values
string

joinLanguageScoped()

Adds `LEFT JOIN root.relation alias WITH alias.languageId = N` and returns its alias.

private static joinLanguageScoped(QueryBuilder $qb, string $fromTableAlias, string $relation, int $languageId) : string

The join has its own alias (not one from JoinHelper), so the language condition does not narrow a join that other conditions (fulltext, parameters) filter through. Repeated calls do not add the join again.

Parameters
$qb : QueryBuilder
$fromTableAlias : string
$relation : string
$languageId : int
Return values
string

parseOrderByField()

private static parseOrderByField(string $field) : array{type: "expression", field: string, path: string, expr: string}|array{type: "relation"|"simple", field: string, path: string, expr: null}
Parameters
$field : string
Return values
array{type: "expression", field: string, path: string, expr: string}|array{type: "relation"|"simple", field: string, path: string, expr: null}
On this page

Search results