You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从自定义Repository查询中返回Model实例而非关联数组

解决方案

你有三种可行的方式将查询结果转换为CheckResults模型实例,以下是具体实现:

方案一:使用Extbase标准Repository(推荐)

这是最符合TYPO3 Extbase规范的方式,让Repository继承Extbase的Repository类,利用内置的查询机制自动返回模型实例。

修改CheckResultsRepository代码:

<?php

namespace Homeinfo\SysMon2\Domain\Repository;

use Homeinfo\SysMon2\Domain\Model\CheckResults;
use TYPO3\CMS\Extbase\Persistence\Repository;

final class CheckResultsRepository extends Repository
{    
    public function findBySystem(int $system): array
    {
        $query = $this->createQuery();
        $query->matching(
            $query->equals('system', $system)
        );
        
        // execute()返回QueryResultInterface,toArray()得到模型实例数组
        return $query->execute()->toArray();
    }
}

注意事项

需要确保Extbase知道模型与数据库表的映射关系,在扩展的Configuration/Extbase/Persistence/Classes.php中添加配置:

<?php

declare(strict_types=1);

return [
    \Homeinfo\SysMon2\Domain\Model\CheckResults::class => [
        'tableName' => 'checkresults',
    ],
];

方案二:使用DataMapper自动映射

如果不想让Repository继承Extbase的Repository类,可以注入Extbase的DataMapper来完成数组到模型的自动转换。

修改CheckResultsRepository代码:

<?php

namespace Homeinfo\SysMon2\Domain\Repository;

use Homeinfo\SysMon2\Domain\Model\CheckResults;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;

final class CheckResultsRepository
{    
    public function __construct(
        private readonly ConnectionPool $connectionPool,
        private readonly DataMapper $dataMapper
    ) {
    }

    public function findBySystem(int $system): array
    {
        $queryBuilder = $this->connectionPool->getQueryBuilderForTable('checkresults');
        $result = $queryBuilder
            ->select('*')
            ->from('checkresults')
            ->where(
                $queryBuilder->expr()->eq(
                    'system',
                    $queryBuilder->createNamedParameter($system, Connection::PARAM_INT)
                )
            )
            ->executeQuery();
        
        // 获取关联数组,通过DataMapper映射为模型实例
        $rows = $result->fetchAllAssociative();
        return $this->dataMapper->map(CheckResults::class, $rows);
    }
}

方案三:手动映射数组到模型

适合需要自定义映射逻辑的场景,手动将数据库返回的数组字段赋值给模型实例。

修改CheckResultsRepository代码:

<?php

namespace Homeinfo\SysMon2\Domain\Repository;

use Homeinfo\SysMon2\Domain\Model\CheckResults;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;

final class CheckResultsRepository
{    
    public function __construct(
        private readonly ConnectionPool $connectionPool
    ) {
    }

    public function findBySystem(int $system): array
    {
        $queryBuilder = $this->connectionPool->getQueryBuilderForTable('checkresults');
        $result = $queryBuilder
            ->select('*')
            ->from('checkresults')
            ->where(
                $queryBuilder->expr()->eq(
                    'system',
                    $queryBuilder->createNamedParameter($system, Connection::PARAM_INT)
                )
            )
            ->executeQuery();
        
        $checkResultsList = [];
        // 遍历数据库结果,逐个实例化模型
        foreach ($result->fetchAllAssociative() as $row) {
            $model = new CheckResults();
            
            // 赋值普通类型字段
            $model->id = (int)$row['id'];
            $model->system = (int)$row['system'];
            $model->icmp_request = (bool)$row['icmp_request'];
            $model->ssh_login = $row['ssh_login'];
            $model->http_request = $row['http_request'];
            $model->application_state = $row['application_state'];
            $model->smart_check = $row['smart_check'];
            $model->baytrail_freeze = $row['baytrail_freeze'];
            $model->fsck_repair = $row['fsck_repair'];
            $model->application_version = (bool)$row['application_version'];
            $model->ram_total = (int)$row['ram_total'];
            $model->ram_free = (int)$row['ram_free'];
            $model->ram_available = (int)$row['ram_available'];
            $model->efi_mount_ok = $row['efi_mount_ok'];
            $model->download = (int)$row['download'];
            $model->upload = (int)$row['upload'];
            $model->root_not_ro = $row['root_not_ro'];
            $model->sensors = $row['sensors'];
            $model->in_sync = (bool)$row['in_sync'];
            $model->recent_touch_events = (int)$row['recent_touch_events'];
            
            // 处理DateTime类型字段,需转换为DateTime对象
            if (!empty($row['timestamp'])) {
                $model->timestamp = new \DateTime($row['timestamp']);
            }
            if (!empty($row['offline_since'])) {
                $model->offline_since = new \DateTime($row['offline_since']);
            }
            if (!empty($row['blackscreen_since'])) {
                $model->blackscreen_since = new \DateTime($row['blackscreen_since']);
            }
            
            $checkResultsList[] = $model;
        }
        
        return $checkResultsList;
    }
}

方案对比

  • 方案一:代码简洁,自动处理类型转换、分页、排序等,维护成本最低,优先推荐。
  • 方案二:无需继承Repository,利用Extbase内置工具完成映射,减少手动代码。
  • 方案三:灵活性最高,但代码冗余,字段较多时容易出错,仅适合特殊场景。

内容的提问来源于stack exchange,提问作者user3515670

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 17:40:17