KernelEvents :: REQUEST n'est pas déclenché sur les pages en cache

13

J'essaie d'implémenter un abonné d'événement KernelEvents :: REQUEST pour effectuer une action sur le chargement de la page.

J'ai besoin que cet événement se déclenche, que la page demandée existe ou non dans le cache Drupal - il semble que KernelEvents :: REQUEST ne se déclenche pas lorsque Drupal sert quelque chose à partir du cache.

Y a-t-il un événement que je peux utiliser pour y parvenir, ou dois-je implémenter mes exigences en tant que middleware?

kiamlaluno
la source
1
L'événement REQUEST DOIT être déclenché, sinon il n'y aurait pas de réponse. À mon humble avis, votre ES a un poids insuffisant et le service http_middleware.page_cache (ou le cache de page dynamique) arrête davantage la propagation de l'événement, par conséquent, votre ES ne sera pas déclenché.
Le poids / priorité ES est défini sur 20
Comme l'a écrit 4k4, page_cache pour les utilisateurs anonymes est un middleware et se produit bien avant l'événement REQUEST. Vous pouvez écrire votre propre middleware qui vient plus tôt, mais vous voudrez peut-être reconsidérer votre approche. Que doit-il se passer si tôt? Gardez à l'esprit que la mise en cache de page anonyme peut même se produire dans le vernis d'autres logiciels externes ou même les navigateurs eux-mêmes. Jetez un œil à la façon dont le module de statistiques de base suit les visites de pages: avec javascript qui envoie une requête ping au serveur lorsqu'un utilisateur l'exécute.
Berdir
@Berdir C'est pour fournir une authentification http pour un site, similaire au module Shield - donc je pense que cela représente un exemple valide de quelque chose qui doit être géré le plus tôt possible dans la demande. (Je sais qu'il y a un patch de module D8 Shield implémenté en tant que middleware - je suppose en raison de cette limitation).

Réponses:

14

Le cache dynamique souscrit un événement avec la priorité 27. Si vous voulez que votre code s'exécute avant cela, vous devez utiliser une priorité> 27:

  public static function getSubscribedEvents() {
    $events = [];

    // Run after AuthenticationSubscriber (necessary for the 'user' cache
    // context; priority 300) and MaintenanceModeSubscriber (Dynamic Page Cache
    // should not be polluted by maintenance mode-specific behavior; priority
    // 30), but before ContentControllerSubscriber (updates _controller, but
    // that is a no-op when Dynamic Page Cache runs; priority 25).
    $events[KernelEvents::REQUEST][] = ['onRequest', 27];

Qui exécute DynamicPageCacheSubscriber :: onRequest ..

4k4
la source
La priorité est fixée à 20
Je pense que le problème que vous avez est avec l'événement du cache dynamique, j'ai modifié ma réponse.
4k4
merci @ 4k4, mais même avec une priorité fixée à 30, il se comporte toujours de la même manière (j'ai réinstallé le module et effacé tous les caches après avoir effectué le changement). D'autres idées?
Il y a deux caches. Maintenant que vous avez priorité sur le cache dynamique, il reste le cache de page. Le cache de pages est exécuté avant le noyau principal. Vous pouvez désinstaller ce module et tester si les performances sont bonnes sans lui.
4k4
Je peux confirmer que cela a fonctionné pour moi. J'ai eu une redirection qui ne se produirait qu'une seule fois - avant la mise en cache de la page. Lorsque j'ai ajouté une priorité, ['checkForRediret', 30];cela a fonctionné comme prévu.
Cyclonecode
6

Drupal 8 a un cache à deux niveaux, un cache de page et un cache de page dynamique.

Oui, vous pouvez intercepter le cache de page dynamique comme mentionné @ 4k4. Le problème que vous rencontrez est plus susceptible d'intercepter le cache de pages. La clé est ici .

Il existe quelques solutions pour cela:

  1. Ajoutez une nouvelle classe qui implémente 'HttpKernelInterface' et enregistrez 'http_middleware' avec une priorité supérieure à 200 (280 suffira). Voir la classe 'PageCache' et les implémentations pour les références.

  2. Créez une nouvelle classe pour modifier le «PageCache» existant en l'étendant à partir de «ServiceProviderBase». Vérifiez ceci pour les références ici . Ensuite, créez une nouvelle classe pour étendre le «PageCache».

Voici les références de code:

Il s'agit de StaticCacheServiceProvider.php:

/**
 * Modifies the language manager service.
 */
class StaticCacheServiceProvider extends ServiceProviderBase
{
  /**
   * {@inheritdoc}
   */
  public function alter(ContainerBuilder $container)
  {
    // Overrides language_manager class to test domain language negotiation.
    $definition = $container->getDefinition('http_middleware.page_cache');
    $definition->setClass('Drupal\your_module\StackMiddleware\StaticCache');
  }
}

Voici StaticCache.php:

/**
 * Executes the page caching before the main kernel takes over the request.
 */
class StaticCache extends PageCache
{
  /**
   * {@inheritdoc}
   */
  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
  {
    // do special logic here.

    $response = parent::handle($request, $type, $catch);

    return $response;
  }
}

L'espoir aide.

kororo
la source
C'était très utile, j'ai résolu le problème en implémentant la solution 1.
Remco Hoeneveld