Как создавать встроенные записи (IRRE) с помощью DataHandler в TYPO3?

В нашем случае у нас есть таблица A, которая содержит записи IRRE с использованием таблицы B. Внутри бэкэнд-модуля мы импортируем XML-файл, чтобы импортировать эти записи для таблицы B.

Доступны все записи / данные для таблицы A. Доступны все данные для таблицы B, кроме новых uid / идентификаторов.

На основе https://docs.typo3.org/typo3cms/CoreApiReference/6.2/ApiOverview/Typo3CoreEngine/Database/ Мне нужно установить идентификатор NEWxxxx для всех новых созданных записей.

Я импортирую сразу большое количество записей. Могу ли я сгенерировать эти идентификаторы в цикле и обработать все записи сразу или мне придется запускать всю запись обработки карты данных по записи?

Есть ли какое-либо поле, помимо идентификатора, которое я должен установить в родительской записи, который содержит запись IRRE?

Никакие переводы / рабочие пространства / другие отношения не задействованы.

Спасибо за вашу помощь.


person Maik Peuser    schedule 24.03.2017    source источник
comment
Вам не нужно создавать запись данных по записи, но для массового выполнения вы должны убедиться, что эти NEW... идентификаторы уникальны и не используются повторно для разных данных записи.   -  person Oliver Hader    schedule 24.03.2017


Ответы (1)


DataHandler в TYPO3 использует следующую структуру массива для создания новых или обновления существующих записей - это действительно до TYPO3 CMS 8 включительно:

$dataMap = ['<table-name>' => [
    '<record-uid>' => ['<field-name>' => '<field-value>']
];

Существующие записи используют целочисленное значение поля записи uid, например 123, новые записи используют некоторый случайный, но уникальный идентификатор с префиксом NEW, например NEWa2b3c4f8 создано uniqid('NEW', true) - поскольку для этого можно и нужно использовать TYPO3 CMS 7 StringUtility::getUniqueId('NEW').

Общий пример

Предположим, будут созданы следующие записи:

  • новый элемент содержимого в таблице tt_content
  • two new inline file references for table sys_file_reference for field tt_content.image
    • referencing to existing sys_file record with uid 123
    • ссылка на существующую sys_file запись с uid 234

// generating unique identifiers for records to be created
$ttContentId = 'NEW58d5079c8741c822627844'; // StringUtility::getUniqueId('NEW')
$fileRefId1st = 'NEW58d506f3cd0c4159344142'; // StringUtility::getUniqueId('NEW')
$fileRefId2nd = 'NEW58d50714c1226092562338'; // StringUtility::getUniqueId('NEW')

Подготовка карты данных

Если внимательно присмотреться к tt_content.image, это фактически определение (новых) встроенных ссылок, определенных разделенными запятыми значениями новых или существующих записей - это может быть NEWabc,NEWdef, 123,234,345 или NEWabc,123,NEWdef, смешивая новые и существующие ссылки на записи.

$dataMap = [
  'tt_content' => [
    'NEW58d5079c8741c822627844' => [
      'title' => 'My new content element',
      'bodytext' => 'Look at the following images...',
      'CType' => 'textpic',
      // $fileRefId1st & $fileRefId2nd, the sorting order is defined by this as well
      'image' => 'NEW58d506f3cd0c4159344142,NEW58d50714c1226092562338',
    ],
  ],
  'sys_file_reference' => [
    'NEW58d506f3cd0c4159344142' => [
      'uid_local' => 123,
      'title' => 'Image #123',
    ],
    'NEW58d50714c1226092562338' => [
      'uid_local' => 234,
      'title' => 'Image #234',
    ],
  ]
];

Подготовка команд-карты

// the command-maps is similar to the data-map to copy, localize, move records
// however, it's not required in this scenario and thus stays empty
$commandMap = [];

Выполнение DataHandler

$dataHandler = new \TYPO3\CMS\Core\DataHandling\DataHandler();
$dataHandler->start($dataMap, $commandMap);
$dataHandler->process_datamap();
// $dataHandler->process_cmdmap(); // if $commandMap should be processed as well

Если вам нужны uid созданных записей, это можно решить с помощью внутреннего сопоставления записей DataHandler. Например, следующий код разрешает новый uid созданной записи tt_content:

// fetching the actual record ID, e.g. results in 333
$ttContentId = $dataHandler->substNEWwithIDs['NEW58d5079c8741c822627844'];

Примечания

Определение ссылок происходит в приведенном выше примере непосредственно для поля tt_content.image, которое может содержать NEW... идентификаторов, а также существующие целочисленные идентификаторы. Поведение для всех типов ссылок в TYPO3 одинаково:

  • Тип TCA inline, для всех вариантов (простой, foreign_field, MM)
  • Тип TCA select, для всех вариантов (простой, MM)
  • Тип TCA group, для всех вариантов (простой, MM)

Передача данных через DataHandler гарантирует создание записей журнала, и в большинстве случаев модификации можно отменить с помощью модуля истории / отката TYPO3.

Кроме того, можно выполнять массовые действия - вызов DataHandler не ограничивается только агрегатом (запись tt_content в приведенном выше примере). Однако NEW... идентификаторы должны быть уникальными и не должны повторно использоваться во время массового выполнения, чтобы избежать побочных эффектов.

Преобразован в сценарий table_a & table_b

Если преобразовать это в сценарий table_a и table_b исходного вопроса, $dataMap может выглядеть следующим образом. Конечно, вы должны определить, какие ссылки на table_b привязаны к table_a.

$dataMap = [
  // existing records of table_a, thus using the real ids
  'table_a' => [
    '11' => [ 'reference_field' => 'NEWb1,NEWb2' ],
    '22' => [ 'reference_field' => 'NEWb3,NEWb4' ],
    '33' => [ 'reference_field' => 'NEWb5,NEWb6' ],
  ],
  // new records to be references for table_b, thus using NEW... ids
  'table_b' => [
    'NEWb1' => [ ... field values of this particular table_b record ... ],
    'NEWb2' => [ ... field values of this particular table_b record ... ],
    'NEWb3' => [ ... field values of this particular table_b record ... ],
    'NEWb4' => [ ... field values of this particular table_b record ... ],
    'NEWb5' => [ ... field values of this particular table_b record ... ],
    'NEWb6' => [ ... field values of this particular table_b record ... ],
  ],
];
  

Примечания к идентификаторам

Идентификаторы вроде NEWb1 намеренно сохранены простыми - обычно эти идентификаторы состоят из префикса NEW и (псевдо) случайной шестнадцатеричной строки abdc....

Ядро TYPO3 использует _ 51_, чтобы создать эти уникальные идентификаторы. Однако этого также можно добиться с помощью $id = 'NEW' . bin2hex(random_bytes(10); - идентификаторы просто должны быть уникальными для этого конкретного процесса.

person Oliver Hader    schedule 24.03.2017
comment
Спасибо за подробное описание! - person Jonas Eberle; 03.06.2020
comment
В v9 мне пришлось заполнить sys_file_reference дополнительными данными: [ 'table_local' => 'sys_file', 'uid_local' => $_file->getUid(), 'tablenames' => 'tx_slider_domain_model_layer', 'uid_foreign' => $_newL, 'fieldname' => 'media', 'pid' => 1, ] - uid_local в моем случае было недостаточно. - person Jonas Eberle; 03.06.2020
comment
Не работает, если в идентификаторе есть нижнее подчеркивание. Так, например, NEW_b_1 не работает, но NEWb1 в порядке. - person Rintisch; 27.04.2021
comment
NEW_b_1 и др. Были использованы в качестве примеров - как указывалось ранее, эти значения должны быть уникальными и генерироваться с использованием StringUtility::getUniqueId('NEW'). Во всяком случае, я удалил подчеркивания и добавил еще один раздел примечаний по идентификаторам ... - person Oliver Hader; 27.04.2021