TYPO3插件如何用Extbase模型访问外部MySQL/MariaDB数据库?
TYPO3插件跨数据库访问实现方案
问题背景
我正在编写一个TYPO3插件,需要访问一台可配置的MySQL/MariaDB服务器上的预定义结构数据库表。当前编写的CheckResults模型默认会指向TYPO3本地数据库,无法连接外部数据库,希望用高层抽象(避免原生SQL)实现跨库访问,需支持配置外部库的主机、端口、用户名、密码。
模型代码如下:
<?php namespace Homeinfo\SysMon2\Domain\Model; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; class CheckResults extends AbstractEntity { /** * @var int $id */ public $id; /** * @var DateTime $timestamp */ public $timestamp; /** * @var int $system */ public $system; /** * @var bool $icmp_request */ public $icmp_request; /** * @var string $ssh_login */ public $ssh_login ; /** * @var string $http_request */ public $http_request; /** * @var string $application_state */ public $application_state; /** * @var string $smart_check */ public $smart_check; /** * @var string $baytrail_freeze */ public $baytrail_freeze; /** * @var string $fsck_repair */ public $fsck_repair; /** * @var bool $application_version */ public $application_version; /** * @var int $ram_total */ public $ram_total; /** * @var int $ram_free */ public $ram_free; /** * @var int $ram_available */ public $ram_available; /** * @var string $efi_mount_ok */ public $efi_mount_ok; /** * @var int $download */ public $download; /** * @var int $upload */ public $upload; /** * @var string $root_not_ro */ public $root_not_ro; /** * @var string $sensors */ public $sensors; /** * @var bool $in_sync */ public $in_sync; /** * @var int $recent_touch_events */ public $recent_touch_events; /** * @var DateTime $offline_since */ public $offline_since; /** * @var DateTime $blackscreen_since */ public $blackscreen_since; }
实现步骤
1. 配置外部数据库连接
方式一:直接在系统配置中添加
在typo3conf/LocalConfiguration.php或AdditionalConfiguration.php中写入外部数据库连接参数:
$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['sysmon_db'] = [ 'driver' => 'mysqli', 'host' => '外部数据库主机地址', 'port' => 3306, 'dbname' => '目标数据库名', 'user' => '数据库用户名', 'password' => '数据库密码', 'charset' => 'utf8mb4', ];
方式二:通过插件配置界面让用户设置
在插件的ext_conf_template.txt中添加配置项:
sysmon_db_host = type = input label = 外部数据库主机地址 sysmon_db_port = 3306 type = input label = 外部数据库端口 sysmon_db_name = type = input label = 数据库名称 sysmon_db_user = type = input label = 数据库用户名 sysmon_db_password = type = input label = 数据库密码 renderType = password
然后在ext_localconf.php中读取配置并注入数据库连接:
$extConf = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( \TYPO3\CMS\Core\Configuration\ExtensionConfiguration::class )->get('sys_mon2'); $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['sysmon_db'] = [ 'driver' => 'mysqli', 'host' => $extConf['sysmon_db_host'] ?? '', 'port' => (int)$extConf['sysmon_db_port'] ?? 3306, 'dbname' => $extConf['sysmon_db_name'] ?? '', 'user' => $extConf['sysmon_db_user'] ?? '', 'password' => $extConf['sysmon_db_password'] ?? '', 'charset' => 'utf8mb4', ];
2. 自定义Repository并绑定外部连接
创建对应CheckResults的Repository类,继承Extbase的Repository,并在初始化时指定外部数据库连接:
<?php namespace Homeinfo\SysMon2\Domain\Repository; use TYPO3\CMS\Extbase\Persistence\Repository; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Utility\GeneralUtility; class CheckResultsRepository extends Repository { protected $connectionName = 'sysmon_db'; protected $tableName = 'check_results'; // 外部数据库中的实际表名 public function initializeObject() { // 禁用TYPO3默认的页面树限制(外部表无pages字段) $querySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface::class); $querySettings->setRespectStoragePage(false); $this->setDefaultQuerySettings($querySettings); // 绑定外部数据库连接到Repository的数据映射器 $dataMapper = $this->objectManager->get( \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class ); $dataMapper->setTableName($this->tableName); $dataMapper->setConnectionName($this->connectionName); $backend = $this->persistenceManager->getBackend(); $backend->setDataMapper($dataMapper); } // 自定义查询示例:按system字段筛选 public function findBySystemId(int $systemId) { $query = $this->createQuery(); $query->matching( $query->equals('system', $systemId) ); return $query->execute(); } }
3. 调整模型注解(可选)
为模型添加表名和主键注解,明确映射关系:
/** * @TYPO3\CMS\Extbase\Annotation\ORM\Table(name="check_results") */ class CheckResults extends AbstractEntity { /** * @var int $id * @TYPO3\CMS\Extbase\Annotation\ORM\Id */ public $id; // ... 原有属性 }
4. 在控制器中使用Repository
通过依赖注入引入Repository,即可像操作本地数据一样调用高层抽象方法:
<?php namespace Homeinfo\SysMon2\Controller; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use Homeinfo\SysMon2\Domain\Repository\CheckResultsRepository; class CheckResultsController extends ActionController { protected CheckResultsRepository $checkResultsRepository; public function injectCheckResultsRepository(CheckResultsRepository $checkResultsRepository) { $this->checkResultsRepository = $checkResultsRepository; } public function listAction() { // 获取全部记录 $allResults = $this->checkResultsRepository->findAll(); // 调用自定义查询 $specificResults = $this->checkResultsRepository->findBySystemId(123); $this->view->assignMultiple([ 'allResults' => $allResults, 'specificResults' => $specificResults ]); } }
注意事项
- 确保外部数据库服务器开放TYPO3服务器IP的访问权限
- 外部表字段类型需与模型属性类型对应(如
DateTime对应数据库datetime类型) - 若外部表主键不是
uid,必须通过@ORM\Id注解指定主键字段
内容的提问来源于stack exchange,提问作者user3515670
相关产品推荐
相关产品推荐

