TYPO3 11.5同一模型双向关联失效问题求助
解决TYPO3 11.5自关联双向关联问题
1. 确认MM表结构
首先确保你的tx_atto_domain_model_atto_mm表包含以下字段,以支持多语言和工作区同步:
CREATE TABLE tx_atto_domain_model_atto_mm ( uid_local int(11) unsigned DEFAULT '0' NOT NULL, uid_foreign int(11) unsigned DEFAULT '0' NOT NULL, sorting int(11) unsigned DEFAULT '0' NOT NULL, sorting_foreign int(11) unsigned DEFAULT '0' NOT NULL, sys_language_uid int(11) DEFAULT '0' NOT NULL, workspace_id int(11) DEFAULT '0' NOT NULL, PRIMARY KEY (uid_local, uid_foreign, sys_language_uid, workspace_id), KEY uid_local (uid_local), KEY uid_foreign (uid_foreign) );
如果原表缺少sorting_foreign、sys_language_uid或workspace_id,需要补充这些字段,否则双向排序和工作区同步会失效。
2. 配置双向TCA字段
在tx_atto_domain_model_atto的TCA中,除现有atto字段外,添加反向关联字段(示例命名为related_attos),并修正原字段的配置错误:
原字段(atto)调整
修正foreign_table_where中的表名错误(你当前写的tx_atto_domain_model_modelloatto应为tx_atto_domain_model_atto),并指定反向关联字段:
'atto' => [ 'exclude' => true, 'label' => '关联的Atti', 'config' => [ 'type' => 'group', 'internal_type' => 'db', 'allowed' => 'tx_atto_domain_model_atto', 'MM' => 'tx_atto_domain_model_atto_mm', 'foreign_table' => 'tx_atto_domain_model_atto', 'foreign_table_where' => 'AND (tx_atto_domain_model_atto.sys_language_uid IN (-1,0) OR tx_atto_domain_model_atto.l10n_parent = 0) ORDER BY tx_atto_domain_model_atto.title', 'MM_opposite_field' => 'related_attos', 'size' => 10, 'minitems' => 0, 'maxitems' => 99, 'fieldControl' => [ 'editPopup' => [ 'disabled' => false, 'options' => [ 'type' => 'popup', 'title' => '编辑', 'module' => ['name' => 'wizard_edit'], 'popup_onlyOpenIfSelected' => true, 'icon' => 'actions-open', 'JSopenParams' => 'height=350,width=580,status=0,menubar=0,scrollbars=1', ], ], 'listModule' => [ 'disabled' => false, 'options' => [ 'type' => 'script', 'title' => '列表', 'icon' => 'actions-system-list-open', 'params' => ['table' => 'tx_atto_domain_model_atto'], 'module' => ['name' => 'wizard_list'], ], ], ], 'behaviour' => [ 'allowLanguageSynchronization' => true, ], ], ],
添加反向关联字段(related_attos)
'related_attos' => [ 'exclude' => true, 'label' => '被关联的Atti', 'config' => [ 'type' => 'group', 'internal_type' => 'db', 'allowed' => 'tx_atto_domain_model_atto', 'MM' => 'tx_atto_domain_model_atto_mm', 'foreign_table' => 'tx_atto_domain_model_atto', 'foreign_table_where' => 'AND (tx_atto_domain_model_atto.sys_language_uid IN (-1,0) OR tx_atto_domain_model_atto.l10n_parent = 0) ORDER BY tx_atto_domain_model_atto.title', 'MM_opposite_field' => 'atto', 'size' => 10, 'minitems' => 0, 'maxitems' => 99, 'fieldControl' => [ 'editPopup' => [ 'disabled' => false, 'options' => [ 'type' => 'popup', 'title' => '编辑', 'module' => ['name' => 'wizard_edit'], 'popup_onlyOpenIfSelected' => true, 'icon' => 'actions-open', 'JSopenParams' => 'height=350,width=580,status=0,menubar=0,scrollbars=1', ], ], 'listModule' => [ 'disabled' => false, 'options' => [ 'type' => 'script', 'title' => '列表', 'icon' => 'actions-system-list-open', 'params' => ['table' => 'tx_atto_domain_model_atto'], 'module' => ['name' => 'wizard_list'], ], ], ], 'behaviour' => [ 'allowLanguageSynchronization' => true, ], ], ],
3. 配置模型类的双向关联
在Atto.php模型中添加对应属性和Doctrine注解,确保ORM层面的双向关联生效:
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; use Doctrine\ORM\Mapping as ORM; class Atto extends AbstractEntity { /** * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Vendor\Atto\Domain\Model\Atto> * @ORM\ManyToMany(targetEntity="\Vendor\Atto\Domain\Model\Atto", inversedBy="relatedAttos") * @ORM\JoinTable( * name="tx_atto_domain_model_atto_mm", * joinColumns={@ORM\JoinColumn(name="uid_local", referencedColumnName="uid")}, * inverseJoinColumns={@ORM\JoinColumn(name="uid_foreign", referencedColumnName="uid")} * ) */ protected $atto; /** * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Vendor\Atto\Domain\Model\Atto> * @ORM\ManyToMany(targetEntity="\Vendor\Atto\Domain\Model\Atto", mappedBy="atto") */ protected $relatedAttos; public function __construct() { $this->atto = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage(); $this->relatedAttos = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage(); } // 生成$atto和$relatedAttos的getter、setter、add/remove方法 // ... }
注意替换Vendor\Atto为你的扩展命名空间。
4. 不推荐使用保存钩子的原因
保存钩子(如processDatamap_afterDatabaseOperations)不是最优方案:
- 无法原生兼容工作区:会绕过TYPO3工作区的发布机制,导致数据不一致。
- 维护成本高:需手动处理MM表的增删改,易出现多语言、排序等边界错误。
- TYPO3原生MM双向关联已支持工作区和多语言,配置正确即可自动处理。
5. 验证工作区兼容性
MM表包含workspace_id字段后,TYPO3会自动处理工作区关联:
- 工作区内的关联变更会被记录到对应版本的MM记录中。
- 发布工作区时,关联会同步到主工作区。
- 多语言同步通过
allowLanguageSynchronization配置自动生效。
内容的提问来源于stack exchange,提问作者MarioProject
相关产品推荐
相关产品推荐

