如何让TCA字段foreign_table_where遵循Extbase storage pid配置?
我开发了一款支持多语言、多域名的Extbase扩展,遇到了TCA字段相关问题。控制器与仓储可根据各根页面定义的persistence.storagePid常量获取结果,但selectMultipleSideBySide类型的TCA字段无法实现该效果,当前配置如下:
'config' => [ 'type' => 'select', 'renderType' => 'selectMultipleSideBySide', 'MM' => 'tx_lmyext_domain_model_model1_mm', 'foreign_table' => 'tx_myext_domain_model_model1', 'foreign_table_where' => ' AND tx_myext_domain_model_model1.sys_language_uid IN (-1,###REC_FIELD_sys_language_uid###) ORDER BY tx_locationslist_domain_model_model1.title', 'maxitems' => 1, ],
持久化设置对该查询无作用,选择字段右侧显示了数据库中所有对象,示例如下:
| 多选左列 | 多选右列 |
|---|---|
| 来自PID 200的对象 | |
| 来自PID 200的对象 | |
| 来自PID 90的对象 <- 不应在此处 |
选中“来自PID 90的对象”后,前端因仓储查询设置不会显示,但编辑器仍可在TCA字段中选择它。
请问是否有办法仅显示指定PID的条目,类似已移除的###STORAGE-PID###标签的效果(如AND tx_myext_domain_model_model1.pid IN (###STORAGE-PID###))?
目前我用AND tx_myext_domain_model_model1.pid IN (###SITEROOT###)实现了近似效果,但这要求所有对象存于各域名的根页面,而我希望将其存于文件夹中。
由于PID会随页面树中选中的页面变化,无法直接在查询中写死PID。
我尝试过PAGE_TSCONFIG_ID标签,效果尚可,但希望仅通过TypoScript常量完成各域名的配置。
也曾尝试使用group元素,但需逐个选择条目,且仍能选中错误PID的对象。
在仓储中通过initializeObject()设置storage pid,也未改变TCA中的可选条目。
方法1:通过TypoScript常量传递存储PID到TCA
可以读取扩展配置中对应的存储PID,动态注入到TCA的查询条件中。在扩展的Configuration/TCA/Overrides/目标表.php中添加代码:
// 读取TypoScript中配置的存储PID $storagePids = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\ExtensionConfiguration::class) ->get('你的扩展密钥', 'storagePid'); // 拼接查询条件到TCA配置 if ($storagePids) { $GLOBALS['TCA']['目标表']['columns']['关联字段名']['config']['foreign_table_where'] .= ' AND tx_myext_domain_model_model1.pid IN (' . $storagePids . ')'; }
多域名场景下,确保每个根页面的TypoScript常量正确覆盖plugin.tx_你的扩展.persistence.storagePid,并同步到扩展配置中。
方法2:结合站点配置动态获取存储PID
在站点配置中添加自定义字段存储模型文件夹PID,然后在TCA中根据当前编辑页面的站点读取对应值:
$currentPageId = (int)$_GET['id'] ?? 0; $site = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Site\SiteFinder::class) ->getSiteByPageUid($currentPageId); $storagePid = $site->getConfiguration()['你的扩展']['storagePid'] ?? ''; if ($storagePid) { $GLOBALS['TCA']['目标表']['columns']['关联字段名']['config']['foreign_table_where'] .= ' AND tx_myext_domain_model_model1.pid IN (' . $storagePid . ')'; }
这种方式支持多站点独立配置存储PID,无需硬编码值,适配不同域名的文件夹存储需求。
方法3:使用userFunc生成动态查询条件
如果需要更灵活的逻辑(比如根据当前编辑页面的根页面匹配对应存储PID),可以自定义userFunc来扩展查询条件:
首先修改TCA配置:
'config' => [ // 原有配置... 'foreign_table_where' => 'AND tx_myext_domain_model_model1.sys_language_uid IN (-1,###REC_FIELD_sys_language_uid###) ORDER BY tx_locationslist_domain_model_model1.title', 'userFunc' => \你的命名空间\Tca\ForeignTableWhereHandler::class . '->addStoragePidCondition', ],
然后创建对应的处理类:
<?php namespace 你的命名空间\Tca; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Site\SiteFinder; class ForeignTableWhereHandler { public function addStoragePidCondition(&$parameters) { $currentPageId = (int)$_GET['id'] ?? 0; $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageUid($currentPageId); // 从站点配置或TypoScript读取存储PID $storagePid = $site->getConfiguration()['plugin.tx_你的扩展.persistence.storagePid'] ?? ''; if ($storagePid) { $parameters['additionalWhereClause'] .= ' AND tx_myext_domain_model_model1.pid IN (' . $storagePid . ')'; } } }
这种方式完全自定义逻辑,适配复杂的多站点、多存储PID场景。
注意事项
- 已移除的
###STORAGE-PID###标签无法再使用,不要在静态TCA中尝试。 - 多个存储PID用逗号分隔,例如
200,201。 - 修改TCA后必须清理TYPO3缓存才能生效。
内容的提问来源于stack exchange,提问作者Birne125

