У меня есть два модуля, module_alpha и module_beta.
Оба модуля устанавливают таблицу базы данных с крючок_схема()
которые они используют для отслеживания информации об опубликованных узлах. Данные заносятся в таблицу с сервисными методами, выполняемыми из крюк_узел_вставка ()
и крючок_node_update()
крючки. Это все работает.
Но мне нужно обработать все существующие узлы, когда модуль установлен, чтобы заполнить пользовательские таблицы информацией об уже существующих опубликованных узлах.Каждый модуль реализует крючок_установить ()
и использует пакетный процесс для обработки всех существующих опубликованных узлов. Однако я наблюдаю странные несоответствия. Иногда пакетный процесс выполняется, иногда нет. Сценарий может работать для одного модуля, но не для другого. И все это несмотря на то, что код почти идентичен. Вот сценарии, которые я тестировал:
Метод установки модуля |
Альфа-модуль |
Бета-версия модуля |
drush en MYMODULE |
Пакетное выполнение |
Пакет не выполняется |
драш цим |
Пакет не выполняется |
Пакет не выполняется |
Пользовательский интерфейс, включить модуль из /admin/modules |
Пакетное выполнение |
Пакетное выполнение |
Пользовательский интерфейс, конфигурация синхронизации из /admin/config/development/configuration |
Пакетное выполнение |
Пакетное выполнение |
Пакетное выполнение указывает, что пакет выполняется полностью, как и ожидалось, с сообщениями о ходе выполнения, и моя таблица заполнена данными. Пакет не выполняется указывает, что пакет вообще не выполняется. Сообщения об ошибках не отображаются и не сохраняются в журналах. Самое странное в этих данных то, что drush en module_alpha
всегда удается и drush en module_beta
всегда терпит неудачу.
Что может быть причиной того, что пакетный процесс работает в одних случаях, но не работает в других? Как я могу последовательно выполнять этот пакетный процесс во всех 4 этих методах, независимо от того, включен ли модуль через пользовательский интерфейс или drush? Честно говоря, единственный метод, который я буду использовать, это драш цим
Код:
В MYMODULE.install:
функция МОЙМОДУЛЬ_установить () {
$batch = новый \Drupal\Core\Batch\BatchBuilder();
$ партия
->setTitle(t('Массовая обработка существующих элементов.'))
// Эта операция ссылается на другую функцию для каждого модуля.
// В обоих случаях функция находится в MYMODULE.module, и код почти идентичен.
->addOperation('_MYMODULE_initialize_items', []);
batch_set($batch->toArray());
}
В МОЙМОДУЛЬ.модуль:
функция _MYMODULE_initialize_items(&$context) {
$batch_size = 25;
$entity_type = 'узел';
// Я нацеливаюсь на разные пакеты в module_alpha и module_beta.
$bundle = 'MY_TARGET_BUNDLE';
if (!isset($context['sandbox']['processed'])) {
$context['sandbox']['processed'] = 0;
}
если (пусто($context['sandbox']['entity_ids'])) {
$context['sandbox']['entity_ids'] = \Drupal::entityTypeManager()
-> получить хранилище ($ тип_сущности)
-> получить запрос ()
->условие('тип', $комплект)
->условие('статус', 1)
->выполнить();
если (is_array($context['sandbox']['entity_ids'])) {
$context['sandbox']['total'] = count($context['sandbox']['entity_ids']);
}
}
если (!пусто($context['песочница']['entity_ids'])) {
$current_batch_ids = array_slice($context['sandbox']['entity_ids'], $context['sandbox']['processed'], $batch_size);
$current_batch_entities = \Drupal::entityTypeManager()
-> получить хранилище ($ тип_сущности)
->loadMultiple($current_batch_ids);
foreach ($current_batch_entities как $entity) {
// Я использую разные сервисы и методы в module_alpha и module_beta.
\Drupal::service('MYMODULE.my_service')
->процессЭнтити($сущность);
$context['sandbox']['processed']++;
}
}
если (!пусто($context['песочница']['всего'])) {
$context['finished'] = $context['sandbox']['processed'] / $context['sandbox']['total'];
$context['message'] = t('Обработано @обработано из @всего элементов.', [
'@processed' => $context['sandbox']['processed'],
'@total' => $context['sandbox']['total'],
]);
}
еще {
$context['завершено'] = 1;
}
}
Пример сервисного метода, вызываемого в пакетном процессе:
общедоступная функция processEntity (EntityInterface $entity) {
// $this->db внедряется в службу `@database`, т.е. \Drupal::service('database');
вернуть $this->db
->вставить('МОЙ МОДУЛЬ_mytable')
->поля([
'entity_type' => $entity->getEntityTypeId(),
'entity_bundle' => $entity->bundle(),
'entity_uuid' => $entity->uuid(),
// и т.д...
])
->выполнить();
}