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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:53:18