【问题标题】:Compare two database fields in extbase repository比较 extbase 存储库中的两个数据库字段
【发布时间】:2019-03-07 17:18:48
【问题描述】:

我正在使用 TYPO3 8。在我的扩展中,我有一个数据库表“company”,其中存储了每个公司的总位置数 (number_places) 和占用位置数 (occupied_places)。 现在我想将搜索限制在有空位的公司。 在 MySQL 中是这样的:

SELECT * FROM company WHERE number_places > occupied_places;

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

我尝试在模型中引入虚拟属性placesLeft,但没有成功。

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

Extbase query to compare two fields in same table

【问题讨论】:

    标签: repository typo3 extbase typo3-8.x


    【解决方案1】:

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

    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;
        }
    }
    

    注意事项:

    • 如果您有很多记录要处理,出于性能原因,我将不使用数据映射功能并使用数组。

    • 如果您想使用流畅的分页小部件,请确保您不要并构建您自己的分页。由于这种工作方式(extbase-internally),当表增长时,您将获得巨大的系统负载开销。更好地将对有限 db 查询的支持添加到存储库方法中,例如:

    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】:

    我认为你不能使用默认的 Extbase 查询方法来做到这一点,比如 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 注入的每个值。

    【讨论】:

      【解决方案3】:

      基于 TYPO3 的当前架构,数据结构是这样的:比较两个表,或者混合两个表的结果应该在 controller 中通过注入两个存储库来完成。 (可选)在例程的情况下,您可以构建一个域服务,该服务可以处理来自 action 本身的两个存储库中的数据。服务也必须注入。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-23
        • 1970-01-01
        • 2011-11-28
        • 1970-01-01
        • 2019-11-20
        • 2017-01-22
        相关资源
        最近更新 更多