Code funktioniert nur im Dev Modus

Hallo Leute, bin etwas perplex. Folgender Code funktioniert nur im dev Modus der .env, wie er sollte. Wechsle ich auf den prod Modus, wird einmal auf die eingegebene Route reagiert, und das bleibt dann so. Den Cache habe ich geleert. Wenn also die erste eingegebene Route einen 404 Error wirft, weil nur 3 Zahlen eingeben werden, wird ein 404 Error für jede andere URL geworfen, auch wenn sie 10,11 0der 12 Zahlen enthält. Dasselbe gilt vice versa, soll heisen, wenn ich erstmalig eine URL aufrufe, die es nicht gibt und die 11 Ziffern hat, wird weitergeleitet, dann aber immer! Warum ist das so? Warum der Unterschied zwischen dem dev und dem prod Modus? Das ganze funktioniert immer nur dann einmalig wieder, wenn ich php bin/console cache:clear abfeuere, aber eben immer nur einmalig! Ich vermute ein Problem durch das Caching, weiß aber nicht, wie ich es umgehen kann. Einen Eintrag in der twig.yaml(cache:false) brachte nicht den erhofften Erfolg. Das Problem konnte ich lokal nicht reproduzieren…

<?php declare(strict_types=1);

namespace WtChangeURL\Subscriber;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use WtChangeURL\classes\Paths;
use DateTime;
use DateInterval;

class URLSubscriber implements EventSubscriberInterface {

    public static function getSubscribedEvents(): array {
        return [
            KernelEvents::REQUEST => 'onKernelRequest',
        ];
    }

    //TODO: Deployment at live server
    public function onKernelRequest(RequestEvent $event): void {
        file_put_contents($this->logFile(), $this->getDateNTime() . "::Das Plugin WtChangeURL wurde erfolgreich aufgerufen" . PHP_EOL, FILE_APPEND);
        $url2BeRedirected = 'https://shop.de';
        $countDigits = 0;
        $arNumbers = [10, 11, 12];
        $request = $event->getRequest();
        $route2BeCheckedFor404 = $request->attributes->get('_route');
        $uri = $request->getUri();
        file_put_contents($this->logFile(), $this->getDateNTime() . "::Folgende URL wurde aufgerufen:$uri" . PHP_EOL, FILE_APPEND);
        for ($i = 0; $i < strlen($uri); $i++) {
            if (is_numeric($uri[$i])) {
                $countDigits++;
            }
        }
        file_put_contents($this->logFile(), $this->getDateNTime() . "::Anzahl der Nummern in der URL $countDigits" . PHP_EOL, FILE_APPEND);
        if (is_null($route2BeCheckedFor404)) {
            file_put_contents($this->logFile(), $this->getDateNTime() . "::Es wurde ein 404 Error geworfen." . PHP_EOL, FILE_APPEND);
            if (in_array($countDigits, $arNumbers)) {
                $response = new RedirectResponse($url2BeRedirected, 301);
                $event->setResponse($response);
                file_put_contents($this->logFile(), $this->getDateNTime() . "::Da ein 404 Error geworfen wurde und darüber hinaus $countDigits Zahlen in der Uri:$uri enthaltne sind, wird ein Redirect auf:$uri durchgeführt" . PHP_EOL, FILE_APPEND);
            } else {
                file_put_contents($this->logFile(), $this->getDateNTime() . "::Es wurde zwar ein 404 Error geworfen, aber die URL enthielt nur $countDigits Zahlen. Kein Redirect!" . PHP_EOL, FILE_APPEND);
            }
        }
    }

    private function logFile(): string {
        $objPath = new Paths();
        return $objPath->getLogFile();
    }

    private function getDateNTime(): string {
        $now = new DateTime();
        $now = $now->add(new DateInterval('PT2H'));
        return $now->format('Y-m-d H:i:s');
    }
}

Ich habe mich noch nie mit dem Cache auseinandergesetzt, aber von deiner Beschreibung her klingt das logisch.

Die Route wird einmalig erstellt, danach ist diese im Cache. Du musst dann schauen, dass du dein Subscriber nicht statisch (Cache fähig) markierst. Ob das darüber geht oder anders, am besten suchst du da in der Symfony Dokumentation.

Zu cache:false. Hast du danach den Cache geleert? Erst dann wird das wirksam.

Klar, habe ich geleert, mehrmals. Bringt aber nix! Zumindest ist der Subscriber immer noch Cache fähig. Welche Symfony Doku würdest Du mir denn empfehlen?
P.S.: Warum ist die Route im dev Modus nicht auch einmalig im Cache? Das leuchtet mir so nicht ein…

Du hast den Subscriber auf den KernelEvents::REQUEST beschränkt. Wenn du dort den Response änderst, hat das keine Auswirkung, weil der Response vom Frontend Controller überschrieben wird. Würde also KernelEvents::RESPONSE ausprobieren oder eine Mischung aus beiden Events.

    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::REQUEST => 'onRequest',
            KernelEvents::RESPONSE => 'onResponse'
        ];
    }

    public function onRequest(RequestEvent $event): void
    {
        // If is not normal request then do nothing
        if ($event->getRequest()->isXmlHttpRequest()) {
            return;
        }
        // If is not sales channel request then do nothing
        if (!$event->getRequest()->attributes->has(SalesChannelRequest::ATTRIBUTE_IS_SALES_CHANNEL_REQUEST)) {
            return;
        }
        $salesChannelId = $event->getRequest()->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID);
        if (!$salesChannelId) {
            return;
        }
   }

Dein Code verwendet doch auch nur KernelEvents::REQUEST . Außerdem funktioniert die Änderung des Response durchaus, aber aufgrund des Cachings nur ein einziges mal!

Das ist nur ein Teil meines Quelltextes. Welcher Frontend Controller wird angesprochen? Der Cache wird durch den Controller gesetzt. Ist es ein Navigation- oder ProductController, ist der Cache gesetzt - dann den Response subscriben.

Es wird überhaupt kein Controller involviert. Nur der Subscriber!
hier die services.xml, damit klar wird, was alles involviert ist…

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
    <services>
        <service id="WtChangeURL\Subscriber\URLSubscriber">
            <tag name="kernel.event_subscriber"/>
        </service>
    </services>
</container>

Ja, vllt ist das das Problem. Es gibt keine Route und kein Controller, der Pfad ist also automatisch nicht vorhanden und wirft einen 404. Da kein HttpCacheKey generiert wurde, ist dann auch jeder weitere Aufruf ein 404 bzw eine Weiterleitung.

Meine Empfehlung ist den KernelEvents::RESPONSE zu subscriben, da dies zu 100% die letzte Instanz des Response ist und auch mehr Priorität hat, als ein CachedResponse. VG

1 „Gefällt mir“

Hallo Moorleiche, vorab vielen Dank für Deinen Einsatz. Leider ist Dein Ansatz der Falsche. Ich habe sehr wohl eine Route, sofern es sie gibt, sofern es also einen Eintrag in der Tabelle seo_url gibt, ist $route2BeCheckedFor404 nämlich nicht null, und es wird auch kein 404 Error geworfen. Die Frage ist eher: Warum klappt mein Code nur im dev Modus bzw. warum wird im prod Modus gecacht und wie kann ich das abstellen…
Der Ansatz von Max_Shop ist da vielversprechender, allerdings weiß ich leider immer noch nicht, wie ich das Caching effektiv abstellen kann, und vor allem nicht, warum nur im prod Modus gecacht wird!
Beispiel:https://shop.de/Main-product-with-advanced-prices/52001 gibt es, also kein Redirecting
$route2BeCheckedFor404 wird gecacht
https://shop.de/Main-product-with-advanced-prices/52002 gibt es nicht, der gecachte Aufruf wird verarbeitet und die Kondition bleibt false.
Dasselbe gilt natürlich vice versa, aber nur im prod Modus, soll heisen
https://shop.de/Main-product-with-advanced-prices/52002 gibt es nicht, also einmalig ein Redirecting
$route2BeCheckedFor404 wird gecacht,
https://shop.de/Main-product-with-advanced-prices/52001 gibt es, kein Redirecting
https://shop.de/Main-product-with-advanced-prices/52 gibt es nicht, dürfte aufgrund nur zweier Zahlen aber nicht redirected werden, wird es aber trozdem aufgrund des Cachings…

hier könnte es ggf. drin stehen.

Wieso es im dev kein Cache gibt? Da man ständig etwas ändert und sehen möchte ob es tut, ohne ständig den Cache leeren zu müssen.

Hi Max_Shop,
vielen Dank für Deinen Link und für Deine Erklärung bzgl. des dev Modus. Schaue mir das beizeiten an und melde mich wieder, sobald ich näheres weiß…