比较extbase存储库中的两个数据库字段

时间:2019-03-07 17:18:49

标签: repository typo3 extbase typo3-8.x

我正在使用TYPO38。在我的扩展程序中,我有一个数据库表“ company”,在其中为每个公司存储总位数(number_places)和已占用位数(occupied_places)。 现在,我想将搜索范围限制为还有剩余可用地点的公司。 在MySQL中,将是这样的:

SELECT * FROM company WHERE number_places > occupied_places;

如何在extbase存储库中创建此查询?

我试图在我的模型中引入虚拟财产placeLeft,但是没有用。

我不想使用下面提到的原始SQL语句,因为我已经实现了一个使用很多不同约束的过滤器。

Extbase query to compare two fields in same table

3 个答案:

答案 0 :(得分:1)

我认为您不能使用默认的Extbase Query方法(例如equals()等)来执行此操作。您可以像这样对特定查询使用函数$query->statement()。 从TYPO3 8开始,您还可以使用QueryBuilder,它具有将字段相互比较的功能: https://docs.typo3.org/typo3cms/CoreApiReference/latest/ApiOverview/Database/QueryBuilder/Index.html#quoteidentifier-and-quoteidentifiers 在Extbase存储库中使用此QueryBuilder很好。之后,您可以使用DataMapper将查询结果映射到Extbase模型。

在使用“ statement()”的情况下,请注意转义每个可能导致任何类型的SQL注入的值。

答案 1 :(得分:1)

您可以在存储库类中这样做,请注意代码中的注释:

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();
        // ...
    }
}

答案 2 :(得分:0)

基于TYPO3的当前体系结构,数据结构使得可以比较两个表,或者应该通过注入两个存储库在controller内完成两个表的混合结果。 (可选)您可以构造一个域服务,在例行程序的情况下,该域服务可以处理action自身内部两个存储库中的数据。该服务也必须被注入。

注意: 如果在表配置中定义了外部关系,则该外部关系的结果将显示在定义的表存储库中。所以,也有。