Рейтинг:-1

Не удается получить html страницы после обновления страницы и сброса всех кешей

флаг gb

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

функция mymodulename_node_update($node) {
    drupal_flush_all_caches();
    $nid = $node->nid->значение;
    $nodePath = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'.$nid);
    $content = file_get_contents('https://mydomain.com'.$nodePath);
    file_put_contents(__DIR__ . '/test.html', $content);
}

Но через долгое время (дольше, чем время обычной очистки кешей через админку) я просто получаю ошибку

"file_get_contents(https://mydomain.com/путь к странице): не удалось открыть поток: Ошибка HTTP-запроса! в..."

и запись в файл не выполняется.

Если я попытаюсь получить контент через cURL, страница панели администратора никогда не загрузится.

Что не так?

leymannx avatar
флаг ne
Разве это не просто `$node->id()`?
leymannx avatar
флаг ne
Вы знаете [Томе] (https://www.drupal.org/project/tome)? Это генератор статических сайтов для Drupal.
stckvrw avatar
флаг gb
@leymannx Я получаю правильный nid с помощью существующего метода. В любом случае `->id()` все еще не решает проблему
leymannx avatar
флаг ne
Может быть, какой-нибудь php.ini: https://stackoverflow.com/a/3488430/2199525
stckvrw avatar
флаг gb
Нет, если я уберу строку `drupal_flush_all_caches()`, код будет работать правильно
stckvrw avatar
флаг gb
Я даже пытался добавить `sleep(10)` после сброса и до получения содержимого, но безуспешно.
leymannx avatar
флаг ne
Давайте [продолжим это обсуждение в чате](https://chat.stackexchange.com/rooms/128459/discussion-between-leymannx-and-stckvrw).
Рейтинг:2
флаг cn

Это недопустимый вариант использования для drupal_flush_all_caches(). Эта функция предназначена для измененного или нового кода. Для контента вы должны использовать теги кеша.

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

\Drupal\Core\Cache\Cache::invalidateTags(['рендеринг']);

Кстати, операции с сущностями обрабатываются в транзакциях, поэтому параллельный запрос страницы может не увидеть изменения, пока они не будут зафиксированы в базе данных. В этом случае очистка кеша (в любой форме) не помогает.

Изменить: добавление примера для последнего комментария.

Хорошим решением будет обработчик очереди. Он работает в фоновом режиме, без этого вам придется ждать ответа панели администратора после сохранения узла.

Пример:

В хук добавьте элемент очереди с идентификатором сущности:

Медиа::постсохранить()

\Drupal::queue('media_entity_thumbnail')->createItem(['id' => $translation->id()]);

Что добавляет элемент очереди для этого плагина обработки очереди:

/modules/media/src/Plugin/QueueWorker/ThumbnailDownloader.php

<?php

пространство имен Drupal\media\Plugin\QueueWorker;

используйте Drupal\Core\Entity\EntityTypeManagerInterface;
используйте Drupal\Core\Plugin\ContainerFactoryPluginInterface;
используйте Drupal\Core\Queue\QueueWorkerBase;
используйте Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Обработка очереди элементов мультимедиа для получения их миниатюр.
 *
 * @QueueWorker(
 * id = "media_entity_thumbnail",
 * title = @Translation("Загрузчик эскизов"),
 * cron = {"время" = 60}
 * )
 */
class ThumbnailDownloader расширяет QueueWorkerBase, реализует ContainerFactoryPluginInterface {

  /**
   * Служба диспетчера типов сущностей.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  защищенный $entityTypeManager;

  /**
   * Создает новый экземпляр класса.
   *
   * @param массив $configuration
   * Массив конфигурации, содержащий информацию об экземпляре плагина.
   * @param строка $plugin_id
   * plugin_id для экземпляра плагина.
   * @param смешанный $plugin_definition
   * Определение реализации плагина.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   * Служба менеджера типа объекта.
   */
  публичная функция __construct (массив $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  общедоступная статическая функция create(ContainerInterface $container, массив $configuration, $plugin_id, $plugin_definition) {
    вернуть новую статику(
      $ конфигурация,
      $plugin_id,
      $plugin_definition,
      $container->получить('entity_type.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  публичная функция processItem($data) {
    /** @var \Drupal\media\Entity\Media $media */
    if ($media = $this->entityTypeManager->getStorage('media')->load($data['id'])) {
      $media->updateQueuedThumbnail();
      $медиа->сохранить();
    }
  }

}

По умолчанию cron запускается только каждые 3 часа. Если вам нужен статический HTML в более короткие сроки, запустите задачу cron (которая также запускает очереди) за пределами веб-сайта. Видеть https://www.drupal.org/docs/user_guide/en/security-cron.html

stckvrw avatar
флаг gb
Спасибо. Очистка кеша и создание статической страницы предназначены для разных целей — мы просто используем их при обновлении страницы. Мы столкнулись с некоторыми ошибками нашего сайта, появившимися после обновления страницы через панель администратора. Например, содержимое какой-то страницы могло исчезнуть или в ссылках меню появился index.php. И промывка кешей устраняет такие баги.
4uk4 avatar
флаг cn
Вы получаете index.php в кешированных ссылках, если кто-то посещает страницу с URL-адресом, содержащим index.php. Чтобы предотвратить это, вы можете перенаправить такой трафик на чистые URL-адреса с помощью https://www.drupal.org/project/redirect.
stckvrw avatar
флаг gb
Теперь с аннулированием тега мой код работает без ошибки. Но, как вы упомянули, он не видит изменений. Как решить эту проблему? Если я добавлю `sleep(10)` перед получением содержимого, я снова получу ту же прошлую ошибку.
4uk4 avatar
флаг cn
Хорошим решением будет обработчик очереди. Он работает в фоновом режиме, без этого вам придется ждать ответа панели администратора после сохранения узла. И вам не нужно часами ждать, чтобы получить статический html, это не проблема запускать cron каждые 2 или 3 минуты.

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

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