1
votes

I have an A entity and this have a property call B as relation 1:n from B to A. When I update A in TCA backend interface, when an particular field is active, the solution runs a hook of type function processDatamap_postProcessFieldArray (...)

I have to create a new element of B and save in ObjectStorage attribute of A. This works in execute time, create an objet and attaching it, but can not save in DB. I have tried with functions of extbase and Repository but it does not work. In my reserch identified the framework Doctrine for create queries, similar to persistence behavior, but in this case I could save the new object of B.

My question is: how could I use Doctrine for build query that allows to make update for object A, adding the new element B and save this element in the relation in DB.

I am working with TYPO3 7.6

2

2 Answers

3
votes

You shouldn't use Extbase within the DataHandler hooks. Also plain database queries (neither with Dotrine or TYPO3_DB) are not good idea for creating entities within BE. Better way is to use TYPO3 DataHandler API. Example creation of Entity B during create/edit of Entity A could look like that.

Register hook 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();
    }
}

Tested on 8.7, but will work on 7.6 too. Here you can read more about DataHandler https://docs.typo3.org/typo3cms/CoreApiReference/8.7/ApiOverview/Typo3CoreEngine/Database/

2
votes

In contrary to the previous answer, I see no reason, why extbase shouldn`t be used in the DataHandler Hooks. I do it myself in an extension with dynamic objects that are being synchronized via a SOAP-Webservice.

You got to keep few things in mind (in this order inside the hooked function) :

-Obey naming policies !! -Instantiate the ObjectManager manually via GeneralUtility::makeInstance -Get ALL the repositories manually (with all I mean really all.. also repositories of childs of models you are working with inside the hooked function). -Create new object instances with object manager => not with "new".

Then you can just add childs to parents as you are used to.. but dont forget to persistAll() via persistenceManager manually in the end.

Hope this could help. Basically, a function hooked via DataMap Hook acts like a static function called via ajax => you have to make sure to get all the desired utilities and managing classes manually, because typo3 doesn`t auto-inject them.

Hope this helps, Oliver