Рейтинг:2

Невозможно повторно сохранить узлы с помощью entity->save(), особых ошибок нет.

флаг cn

Я пытаюсь написать команду drush для повторного сохранения всех узлов на моем сайте.

Я искал модуль и нашел Пересохранить все узлы модуль, но его команда drush еще не готова. Поэтому я решил попробовать написать его сам.

Однако я не могу заставить свои узлы пересохраняться с помощью $ сущность-> сохранить (), и я не понимаю, почему.

<?php

пространство имен Drupal\resave_all_nodes\Commands;

используйте Drupal\Core\Entity\EntityTypeManagerInterface;
используйте Drupal\node\Entity\Node;
используйте Drush\Commands\DrushCommands;

/**
 * Класс команды Drush для преобразования модуля Resave All Nodes.
 */
класс ResaveAllNodesCommands расширяет DrushCommands
{

  /**
   * Менеджер типов объектов.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  частный $entityTypeManager;


  /**
   * Создает объект ResaveAllNodesCommands.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   * Менеджер типов объектов.
   */
  общедоступная функция __construct (EntityTypeManagerInterface $entity_type_manager)
  {
    $this->entityTypeManager = $entity_type_manager;

    родитель::__construct();
  }

  /**
   * Пересохраните все узлы.
   *
   * @command resave-all-nodes:resave
   *
   * @usage drush resave-all-nodes:resave
   * Пересохранить все узлы на сайте.
   *
   * @псевдонимы побежали
   */
  публичная функция resaveAllNodes()
  {
    $my_node = Node::load(1);
    $my_node->сохранить();
    \Drupal::logger('resave_all_nodes')->notice("узел 1 сохранен!");
  }
}

Когда я запускаю команду, в журналах отображаются уведомления регистратора:

  • Я вижу "узел 1 сохранен!" в журналах
  • У меня есть другое сообщение в журнале hook_entity_presave(), который также появляется

Но, когда я иду в /админ/контент, «дата обновления» для узла 1 не изменилась. Также содержимое узла не сохраняется повторно.

Если я пойду в узел/1/редактировать и повторно сохранить вручную, узел повторно сохраняется, как я и ожидал (обновляется обновленная дата и обновляются значения полей).

Итак, почему узел-> сохранить() молча терпит неудачу (дата обновления и значения полей остаются прежними), при сохранении вручную работает?

У меня есть несколько пользовательских модулей, я отключил их и пересобрал кеш, но проблема осталась.

флаг br
У вас есть какая-то логика, игнорирующая PHP_SAPI, или какой-то модуль игнорирует логику с PHP_SAPI?
флаг cn
@ Джон, я так не думаю. Я только что проверил свою кодовую базу для `PHP_SAPI`, и единственные неосновные ссылки, не относящиеся к Symfony, относятся к модулю веб-форм. Запуск моего сайта локально в ландо, снятом с платформы.sh.
4uk4 avatar
флаг cn
*Но когда я захожу в /admin/content, "дата обновления" для узла 1 не изменилась.* Вам нужно установить измененное время: `$my_node->setChangedTime(\Drupal::time()->getRequestTime ());` Если вы все еще не видите его, попробуйте очистить кеш.
флаг cn
@ 4k4 Хорошо, это сработало. Таким образом, повторное сохранение узла в пользовательском интерфейсе на самом деле отличается от выполнения node->save() тем, что node->save() не вносит никаких изменений, если вы явно не укажете их?
флаг cn
Сущности не сохраняют данные, если ничего не изменилось (по очевидным причинам производительности). Отправка формы сущности обновляет измененную метку времени перед вызовом сохранения, поэтому постоянство активируется. Вам просто нужно сделать то же самое
Рейтинг:2
флаг cn

Благодаря @4k4 и @Clive я смог заставить это работать. Эта команда drush сохраняет все узлы. Далее следует код, но сначала несколько замечаний:

  • После звонка batch_set(), для drush-команд необходимо вызывать drush_backend_batch_process() или партия никогда не будет запущена.
  • Пример модуля пакетной обработки Drush 9 очень полезный пример.
  • В вашей пакетная операция () команда, если вы наберете подсказку $контекст, вы должны использовать \DrushBatchContext|массив $context не просто множество потому что драш сильно разобьется. На drupal.org есть десятки вопросов по этому поводу.

Хорошо, вот мой код:

<?php

пространство имен Drupal\resave_all_nodes\Commands;

используйте Drupal\Core\Batch\BatchBuilder;
используйте Drupal\Core\Entity\EntityTypeManagerInterface;
использовать Drupal\Core\StringTranslation\StringTranslationTrait;
используйте Drush\Commands\DrushCommands;

/**
 * Класс команды Drush для преобразования модуля Resave All Nodes.
 */
класс ResaveAllNodesCommands расширяет DrushCommands
{
  использовать StringTranslationTrait;

  /**
   * Менеджер типов объектов.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  частный $entityTypeManager;


  /**
   * Создает объект ResaveAllNodesCommands.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   * Менеджер типов объектов.
   */
  общедоступная функция __construct (EntityTypeManagerInterface $entity_type_manager)
  {
    $this->entityTypeManager = $entity_type_manager;

    родитель::__construct();
  }

  /**
   * Пересохраните все узлы.
   *
   * @команда пересохранить:узлы
   *
   * @usage drush resave:nodes
   * Пересохранить все узлы на сайте.
   *
   * @псевдонимы побежали
   */
  публичная функция resaveAllNodes()
  {
    // Массив с большим количеством идентификаторов узлов.
    $nids = $this->getNodeIds();
    // Разбить массив на подмассивы (чанки) заданного размера.
    $chunks = array_chunk($nids, 250);
    $num_chunks = количество($кусков);

    // Теперь пересохраняем все узлы по частям.
    $batchBuilder = новый BatchBuilder();
    для ($i = 0; $i < $num_chunks; $i++) {
      $batchBuilder->addOperation('\Drupal\resave_all_nodes\Batch\ResaveAllNodesBatch::batchOperation',
        [$кусков[$i]]
      );
    }

    $batchBuilder->setTitle(t('Пересохранение узлов'))
      ->setFinishCallBack('\Drupal\resave_all_nodes\Batch\ResaveAllNodesBatch::batchFinished');

    batch_set($batchBuilder->toArray());
    drush_backend_batch_process();
  }

  /**
   * Получить идентификаторы узлов массива.
   *
   * @возвратный массив|целое число
   * В лучшем случае массив идентификаторов узлов.
   *
   * @throws\Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws\Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  публичная функция getNodeIds() {
    $query = $this->entityTypeManager->getStorage('node')->getQuery();
    $nids = $запрос->выполнить();
    # Чтобы получить типы узлов.
    # $nids = $query->condition('type', $node_types, 'IN')->execute();

    вернуть $ниды;
  }
}

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.