ezpublish 5.4 根据 parent 字段排序
ezpublish 5.4 sort according to parent field
我正在使用 ezpublish 搜索 API 来获取按 parent 的 training
字段排序的 session
内容类型 objects 的列表(字段名字是 code
).
因此,如果我有两个会话 S1(链接到代码 T1 的培训)和 S2(链接到代码 T2 的培训),我希望在列表中将会话 S1 列在 S2 之前。
$criterions = array (
new Criterion\ContentTypeIdentifier( 'session' )
);
$locationQuery = new LocationQuery();
$locationQuery->query = $criteriaArray;
$locationQuery->sortClauses = array(
//new SortClause\Field('session','price'),<- this works
new SortClause\Field('training','code',Query::SORT_ASC)
//this second sorClause does not work as code is not a field of session while price is
);
使用本机 mysql 查询可能可以解决此问题,但它不可移植,并且某些 ID 将被硬编码。
我的问题是我们能否根据他们的 parent 的 training'
code`字段实现 sesssions
的排序?
不幸的是,内置排序子句无法做到这一点。
您可以做的是获取按 code
字段排序的训练,然后为每个训练分别加载其会话。当然,如果您的数据库中有很多内容对象,这将不会很有效。
另一种可能是实施一个 custom sort clause 来解决问题。
感谢@Edi 和我工作中的一位同事,我设法让它工作。
要创建的两个类是:
字段class:
class ParentSortClauseField extends SortClause
{
public function __construct($typeIdentifier, $fieldIdentifier, $sortDirection = Query::SORT_ASC)
{
parent::__construct(
'field',
$sortDirection,
new FieldTarget($typeIdentifier, $fieldIdentifier)
);
}
}
处理程序class:
class ParentSortClauseHandler extends SortClauseHandler
{
protected $contentTypeHandler;
public function __construct(
DatabaseHandler $dbHandler,
ContentTypeHandler $contentTypeHandler
)
{
$this->contentTypeHandler = $contentTypeHandler;
parent::__construct($dbHandler);
}
public function accept(SortClause $sortClause)
{
return $sortClause instanceof ParentSortClauseField;
}
public function applySelect(SelectQuery $query, SortClause $sortClause, $number)
{
$query
->select(
$query->alias(
$query->expr->not(
$query->expr->isNull(
$this->dbHandler->quoteColumn(
'sort_key_int',
$this->getSortTableName($number)
)
)
),
$column1 = $this->getSortColumnName($number . '_null')
),
$query->alias(
$query->expr->not(
$query->expr->isNull(
$this->dbHandler->quoteColumn(
'sort_key_string',
$this->getSortTableName($number)
)
)
),
$column2 = $this->getSortColumnName($number . '_bis_null')
),
$query->alias(
$this->dbHandler->quoteColumn(
'sort_key_int',
$this->getSortTableName($number)
),
$column3 = $this->getSortColumnName($number)
),
$query->alias(
$this->dbHandler->quoteColumn(
'sort_key_string',
$this->getSortTableName($number)
),
$column4 = $this->getSortColumnName($number . '_bis')
)
);
return array($column1, $column2, $column3, $column4);
}
public function applyJoin(
SelectQuery $query,
SortClause $sortClause,
$number,
array $languageSettings
)
{
/** @var \eZ\Publish\API\Repository\Values\Content\Query\SortClause\Target\FieldTarget $fieldTarget */
$fieldTarget = $sortClause->targetData;
$fieldMap = $this->contentTypeHandler->getSearchableFieldMap();
if (!isset($fieldMap[$fieldTarget->typeIdentifier][$fieldTarget->fieldIdentifier]['field_definition_id'])) {
throw new \InvalidArgumentException(
'$sortClause->targetData',
'No searchable fields found for the given sort clause target ' .
"'{$fieldTarget->fieldIdentifier}' on '{$fieldTarget->typeIdentifier}'."
);
}
$fieldDefinitionId = $fieldMap[$fieldTarget->typeIdentifier][$fieldTarget->fieldIdentifier]['field_definition_id'];
$table = $this->getSortTableName($number);
$query
->innerJoin(
$query->alias('ezcontentobject_tree', 'parent')
,
$query->expr->eq(
$this->dbHandler->quoteColumn('parent_node_id', 'ezcontentobject_tree'),
$this->dbHandler->quoteColumn('node_id', 'parent')
)
);
$query
->leftJoin(
$query->alias(
$this->dbHandler->quoteTable('ezcontentobject_attribute'),
$this->dbHandler->quoteIdentifier($table)
),
$query->expr->lAnd(
$query->expr->eq(
$query->bindValue($fieldDefinitionId, null, PDO::PARAM_INT),
$this->dbHandler->quoteColumn('contentclassattribute_id', $table)
),
$query->expr->eq(
$this->dbHandler->quoteColumn('contentobject_id', $table),
$this->dbHandler->quoteColumn('contentobject_id', 'parent')
),
$query->expr->eq(
$this->dbHandler->quoteColumn('version', $table),
$this->dbHandler->quoteColumn('contentobject_version', 'parent')
),
$query->expr->eq(
$this->dbHandler->quoteColumn('language_code', $table),
$query->bindValue('fre-FR')
)
)
);
}
}
将处理程序声明为服务:
app.sort_clause_handler.location.parent:
class: ...\SortClauseHandler\ParentSortClauseHandler
arguments:
- @ezpublish.api.storage_engine.legacy.dbhandler
- @ezpublish.spi.persistence.content_type_handler
tags:
- {name: ezpublish.search.legacy.gateway.sort_clause_handler.content}
- {name: ezpublish.search.legacy.gateway.sort_clause_handler.location}
为了在控制器中将各个部分组合在一起,我这样做了:
$sortQuery[] = new ParentSortClauseField('parentclassname', 'field', $sortOrder);
我正在使用 ezpublish 搜索 API 来获取按 parent 的 training
字段排序的 session
内容类型 objects 的列表(字段名字是 code
).
因此,如果我有两个会话 S1(链接到代码 T1 的培训)和 S2(链接到代码 T2 的培训),我希望在列表中将会话 S1 列在 S2 之前。
$criterions = array (
new Criterion\ContentTypeIdentifier( 'session' )
);
$locationQuery = new LocationQuery();
$locationQuery->query = $criteriaArray;
$locationQuery->sortClauses = array(
//new SortClause\Field('session','price'),<- this works
new SortClause\Field('training','code',Query::SORT_ASC)
//this second sorClause does not work as code is not a field of session while price is
);
使用本机 mysql 查询可能可以解决此问题,但它不可移植,并且某些 ID 将被硬编码。
我的问题是我们能否根据他们的 parent 的 training'
code`字段实现 sesssions
的排序?
不幸的是,内置排序子句无法做到这一点。
您可以做的是获取按 code
字段排序的训练,然后为每个训练分别加载其会话。当然,如果您的数据库中有很多内容对象,这将不会很有效。
另一种可能是实施一个 custom sort clause 来解决问题。
感谢@Edi 和我工作中的一位同事,我设法让它工作。
要创建的两个类是: 字段class:
class ParentSortClauseField extends SortClause
{
public function __construct($typeIdentifier, $fieldIdentifier, $sortDirection = Query::SORT_ASC)
{
parent::__construct(
'field',
$sortDirection,
new FieldTarget($typeIdentifier, $fieldIdentifier)
);
}
}
处理程序class:
class ParentSortClauseHandler extends SortClauseHandler
{
protected $contentTypeHandler;
public function __construct(
DatabaseHandler $dbHandler,
ContentTypeHandler $contentTypeHandler
)
{
$this->contentTypeHandler = $contentTypeHandler;
parent::__construct($dbHandler);
}
public function accept(SortClause $sortClause)
{
return $sortClause instanceof ParentSortClauseField;
}
public function applySelect(SelectQuery $query, SortClause $sortClause, $number)
{
$query
->select(
$query->alias(
$query->expr->not(
$query->expr->isNull(
$this->dbHandler->quoteColumn(
'sort_key_int',
$this->getSortTableName($number)
)
)
),
$column1 = $this->getSortColumnName($number . '_null')
),
$query->alias(
$query->expr->not(
$query->expr->isNull(
$this->dbHandler->quoteColumn(
'sort_key_string',
$this->getSortTableName($number)
)
)
),
$column2 = $this->getSortColumnName($number . '_bis_null')
),
$query->alias(
$this->dbHandler->quoteColumn(
'sort_key_int',
$this->getSortTableName($number)
),
$column3 = $this->getSortColumnName($number)
),
$query->alias(
$this->dbHandler->quoteColumn(
'sort_key_string',
$this->getSortTableName($number)
),
$column4 = $this->getSortColumnName($number . '_bis')
)
);
return array($column1, $column2, $column3, $column4);
}
public function applyJoin(
SelectQuery $query,
SortClause $sortClause,
$number,
array $languageSettings
)
{
/** @var \eZ\Publish\API\Repository\Values\Content\Query\SortClause\Target\FieldTarget $fieldTarget */
$fieldTarget = $sortClause->targetData;
$fieldMap = $this->contentTypeHandler->getSearchableFieldMap();
if (!isset($fieldMap[$fieldTarget->typeIdentifier][$fieldTarget->fieldIdentifier]['field_definition_id'])) {
throw new \InvalidArgumentException(
'$sortClause->targetData',
'No searchable fields found for the given sort clause target ' .
"'{$fieldTarget->fieldIdentifier}' on '{$fieldTarget->typeIdentifier}'."
);
}
$fieldDefinitionId = $fieldMap[$fieldTarget->typeIdentifier][$fieldTarget->fieldIdentifier]['field_definition_id'];
$table = $this->getSortTableName($number);
$query
->innerJoin(
$query->alias('ezcontentobject_tree', 'parent')
,
$query->expr->eq(
$this->dbHandler->quoteColumn('parent_node_id', 'ezcontentobject_tree'),
$this->dbHandler->quoteColumn('node_id', 'parent')
)
);
$query
->leftJoin(
$query->alias(
$this->dbHandler->quoteTable('ezcontentobject_attribute'),
$this->dbHandler->quoteIdentifier($table)
),
$query->expr->lAnd(
$query->expr->eq(
$query->bindValue($fieldDefinitionId, null, PDO::PARAM_INT),
$this->dbHandler->quoteColumn('contentclassattribute_id', $table)
),
$query->expr->eq(
$this->dbHandler->quoteColumn('contentobject_id', $table),
$this->dbHandler->quoteColumn('contentobject_id', 'parent')
),
$query->expr->eq(
$this->dbHandler->quoteColumn('version', $table),
$this->dbHandler->quoteColumn('contentobject_version', 'parent')
),
$query->expr->eq(
$this->dbHandler->quoteColumn('language_code', $table),
$query->bindValue('fre-FR')
)
)
);
}
}
将处理程序声明为服务:
app.sort_clause_handler.location.parent:
class: ...\SortClauseHandler\ParentSortClauseHandler
arguments:
- @ezpublish.api.storage_engine.legacy.dbhandler
- @ezpublish.spi.persistence.content_type_handler
tags:
- {name: ezpublish.search.legacy.gateway.sort_clause_handler.content}
- {name: ezpublish.search.legacy.gateway.sort_clause_handler.location}
为了在控制器中将各个部分组合在一起,我这样做了:
$sortQuery[] = new ParentSortClauseField('parentclassname', 'field', $sortOrder);