如何在 TYPO3 的钩子中更新具有关系 1:n 的对象

How update object with relation 1:n in a hook in TYPO3

我有一个 A 实体,它有一个 属性 调用 B 作为从 B 到 A 的关系 1:n。当我在 TCA 后端接口中更新 A 时,当特定字段处于活动状态时,解决方案运行 function processDatamap_postProcessFieldArray (...)

类型的挂钩

我必须创建一个新的 B 元素并保存在 A 的 ObjectStorage 属性中。这在执行时有效,创建一个对象并附加它,但不能保存在数据库中。我尝试了 extbase 和 Repository 的功能,但它不起作用。在我的研究中确定了用于创建查询的框架 Doctrine,类似于持久性行为,但在这种情况下我可以保存 B 的新对象。

我的问题是:我如何使用 Doctrine 构建查询,允许对对象 A 进行更新,添加新元素 B 并将该元素保存在数据库中的关系中。

我正在使用 TYPO3 7.6

您不应在 DataHandler 挂钩中使用 Extbase。同样,普通的数据库查询(既不使用 Dotrine 也不使用 TYPO3_DB)对于在 BE 中创建实体不是一个好主意。更好的方法是使用 TYPO3 DataHandler API。在实体 A create/edit 期间创建实体 B 的示例可能看起来像这样。

注册钩子typo3conf/ext/example/ext_localconf.php

defined('TYPO3_MODE') || die('Access denied.');

$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass']['example'] = 'Vendor\Example\DataHandling\DataHandler';

typo3conf/ext/example/Classes/DataHandling/DataHandler.php

namespace Vendor\Example\DataHandling;

use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\StringUtility;

class DataHandler implements SingletonInterface
{
    public function processDatamap_afterDatabaseOperations(
        string $status,
        string $table,
        $id,
        $fieldArray,
        \TYPO3\CMS\Core\DataHandling\DataHandler $dataHandler
    ) {
        // Do nothing if other table is processed
        if ($table !== 'tx_example_domain_model_entitya') {
            return;
        }

        // Get real UID of entity A if A is new record
        $idOfEntityA = $dataHandler->substNEWwithIDs[$id];

        // Example fields of entity B
        $entityB = [
            'sys_language_uid' => '0',
            'entitya' => $idOfEntityA,
            'hidden' => '0',
            'title' => 'I\'m entitty B',
            'starttime' => '0',
            'endtime' => '0',
            'pid' => $fieldArray['pid'],
        ];

        // Add entity B associated with entity A
        $dataHandler->start(
            [
                'tx_example_domain_model_entityb' => [
                    StringUtility::getUniqueId('NEW') => $entityB
                ]
            ],
            []
        );
        $dataHandler->process_datamap();
    }
}

已在 8.7 上测试,但也适用于 7.6。在这里您可以阅读更多关于 DataHandler https://docs.typo3.org/typo3cms/CoreApiReference/8.7/ApiOverview/Typo3CoreEngine/Database/

与之前的回答相反,我看不出为什么不应该在 DataHandler Hooks 中使用 extbase。我自己在一个扩展中使用动态 objects 进行同步,这些动态 objects 通过 SOAP-Webservice.

进行同步

你必须记住一些事情(在钩子函数中按此顺序):

-遵守命名规则!! -通过 GeneralUtility::makeInstance 手动实例化 ObjectManager - 手动获取所有存储库(我的意思是真正的所有..还有您在挂钩函数中使用的模型的子存储库)。 -使用 object 管理器创建新的 object 实例 => 而不是 "new".

然后您可以像往常一样将孩子添加到 parents.. 但不要忘记最后通过 persistenceManager 手动添加 persistAll()。

希望这对您有所帮助。基本上,通过 DataMap Hook 挂钩的函数就像通过 ajax 调用的静态函数一样 => 你必须确保获得所有需要的实用程序并手动管理 类,因为 typo3 不会 auto-inject他们。

希望这对您有所帮助, 奥利弗