我正在使用TYPO3 8.在我的扩展中,我有一个数据库表“company”,其中我为每个公司存储了总的位数(number_places)和占用的位数(occupied_places)。现在我想将搜索范围限制在剩下可用位置的公司。在MySQL中,它将是这样的:
SELECT * FROM company WHERE number_places > occupied_places;
如何在extbase存储库中创建此查询?
我试图在我的模型中引入虚拟属性placesLeft,但它没有用。
我不想使用如下所述的原始SQL语句,因为我已经实现了一个使用大量不同约束的过滤器。
我认为你不能使用默认的Extbase Query方法,比如equals()等。您可以使用$query->statement()
函数来处理这样的特定查询。您也可以使用QueryBuilder,因为TYPO3 8具有相互比较字段的功能:https://docs.typo3.org/typo3cms/CoreApiReference/latest/ApiOverview/Database/QueryBuilder/Index.html#quoteidentifier-and-quoteidentifiers在Extbase存储库中使用此QueryBuilder是可以的。在此之后,您可以使用DataMapper将查询结果映射到Extbase模型。
如果使用“statement()”,请注意转义可能导致任何类型的SQL注入的每个值。
你可以在你的知识库类中这样做,请注意代码中的注释:
class CompanyRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
public function findWithAvailablePlaces(bool $returnRawQueryResult = false)
{
// Create a QueryBuilder instance
$queryBuilder = $this->objectManager->get(\TYPO3\CMS\Core\Database\ConnectionPool::class)
->getConnectionForTable('company')->createQueryBuilder();
// Create the query
$queryBuilder
->select('*')
->from('company')
->where(
// Note: this string concatenation is needed, because TYPO3's
// QueryBuilder always escapes the value in the ExpressionBuilder's
// methods (eq(), lt(), gt(), ...) and thus render it impossible to
// compare against an identifier.
$queryBuilder->quoteIdentifier('number_places')
. \TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder::GT
. $queryBuilder->quoteIdentifier('occupied_places')
);
// Execute the query
$result = $queryBuilder->execute()->fetchAll();
// Note: this switch is not needed in fact. I just put it here, if you
// like to get the Company model objects instead of an array.
if ($returnRawQueryResult) {
$dataMapper = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class);
return $dataMapper->map($this->objectType, $result);
}
return $result;
}
}
笔记:
class CompanyRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
public function findWithAvailablePlaces(
int $limit = 10,
int $offset = 0,
bool $returnRawQueryResult = false
) {
// ...
$queryBuilder
->setMaxResults($limit)
->setFirstResult($offset);
$result = $queryBuilder->execute()->fetchAll();
// ...
}
}