Weiterleiten (forward) in Controller

Hallo,

wir haben ein eigenes Formular erzeugt über ein Plugin mit eigenem Controller und Routes.

Das Formular wird abgeschickt, landet im Controller und wird verarbeitet. Soweit so gut. Allerdings möchten wir nach dem Abschicken natürlich eine Weiterleitung auf eine “Success-Seite”. Oder zumindest einen Success-Response, den ich im Twig-Template verarbeiten und anzeigen kann.

bei $this->forward bzw. $this->forwardToRoute gibts folgenden Error:

PageController can't be requested via XmlHttpRequest.

was machen wir falsch? Wieso kann ich nicht weiterleiten? Ich hab mir die Login-Form angesehen, die funktionert genauso und hier klappt es …

habe sogar das versucht:

header("Location: https://www.myshop.de/");
die();

aber nicht mal das klappt, selbe Fehlermeldung.

 

Hab mir dann das Shopware-Kontaktformular angeschaut. Hier ist kein Forward sondern ein JsonResponse mit Success-Message. Aber wie kann ich in meiner Form die Message anzeigen? Ich bekomm die lediglich als Response des Calls zurück, sehe ich im Netzwerk-Tab. Aber zum Anzeigen müsste ich ja auch die Seite neuladen, oder nicht?

 

Also: wie funktioniert es korrekt?

hat niemand einen Tipp? Eine Idee? Kann doch nicht so schwer sein … oder doch?

Hallo,

ich würde es einfach über:

$finishUrl = $this->generateUrl('frontend.detail.page', ['productId' => $request->get('the_product_id'), 'success' => 1]);

return new RedirectResponse($finishUrl);

lösen (am Beispiel der Produkt - Detailseite, insofern dem Request die Produkt - ID mitgegeben und irgendwo im Template die Variable “success” dann auch interpretiert wird und dort dann über einen Textbaustein eine Erfolgsmeldung erscheint).

Viele Grüße

Sebastian

@sschreier‍ leider funktioniert das auch nicht.

selber Fehler

PageController can't be requested via XmlHttpRequest.

 

Hallo,

ohne das du mal deinen kompletten Code zeigst wird dir hier niemand groß weiterhelfen können. Mein Beispiel funktioniert so auf jeden Fall - außer der Controller wird über Ajax versendet, dann würde ich eher

return new Response('true');

nutzen und dann einfach per JavaScript anhand des callbacks von true an der gewünschten Stelle eine (Erfolgs-)Meldung ausgeben. Deine ganzen Versuche dürften auch problemlos funktionieren, insofern du den Controller nicht über Ajax versendest.
Grüße

Sebastian

hier die Controller-Methode zum Speichern. Da möchte ich dann weiterleiten.

/**
 * @Route("/gallery/save", name="frontend.myplugin.gallery.save", methods={"POST"}, defaults={"XmlHttpRequest"=true})
 * @Captcha
 */
 public function saveUpload(RequestDataBag $data, SalesChannelContext $context): RedirectResponse
 {
        try
        {
            // Daten aus RequestBag speichern, das funktioniert

            $finishUrl = $this->generateUrl('frontend.myplugin.gallery', ['test' => "3333", 'success' => 1]);

            return new RedirectResponse($finishUrl);
        }
        catch (ConstraintViolationException $formViolations)
        {

        }
    }

und die Route zu der ich weiterleiten will

/**
 * @Route("/gallery", name="frontend.myplugin.gallery", options={"seo"="false"}, methods={"GET"})
*/
public function newUpload(Request $request, SalesChannelContext $context): Response
{
        $page = $this->genericLoader->load($request, $context);

        $breadcrumb = [];

        return $this->renderStorefront('@Parent/storefront/gallery/upload.html.twig', [
            'page' => $page,
            'breadcrumbList' => $breadcrumb
        ]);
}

 

hier noch der Netzwerk-Tab der Console

im Preview des roten (der Redirect) steht folgendes

Hallo,

wie gesagt, dann versende die Informationen doch einfach nicht über Ajax, dann kannst du die ganzen genannten Weiterleitungsfunktionen auch nutzen (also return new RedirectResponse($finishUrl)). Es steht doch auch in der Fehlermeldung drin, dass es nicht geht, wenn man einen Ajax - Controller (“PageController can’t be requested via XmlHttpRequest”) nutzt.

Wenn es unbedingt ein Ajax - Controller sein muss, kannst du ja wie erwähnt einfach die Daten zurückgeben lassen (zumindestens “true”, also return new Response(‘true’)) und dann in der callback - Funktion einfach die Weiterleitung über JavaScript machen (die URL zum Weiterleitungscontroller kann man sich ja irgendwo als data-Attribut auf der Seite mit übergeben lassen, sodass man sie in der callback - Funktion aufrufen kann).

Grüße

Sebastian

es muss ja nicht unbedingt Ajax sein, aber ich hab halt das Standard-Kontaktformular für meine Zwecke nachgebaut. Da ist das so.

das geht offenbar dann automatisch über Ajax … wie kann ichs denn anders machen? Kein Plan wieso das ajax wird obwohls ne normale Form-Action ist

Hallo,

wie oben erwähnt hab ich auch eine Möglichkeit genannt, wie man es bei einem Ajax - Controller machen könnte. 

Der Code sieht mir von den CSS - Klassen auch eher nach Shopware 5 als nach Shopware 6 aus.

Ich würde mir wahrscheinlich erstmal Gedanken machen, wer das Formular über Ajax versendet. Alternativ einfach mal die zusätzlichen Attribute entfernen.

Grüße

Sebastian

das ist 1:1 der Code aus Shopware 6 Kontaktformular, nur halt außerhalb einer Erlebniswelt.

Ich hab wirklich Null mit Ajax implementiert, ich hab das Formular in TWIG angelegt, den Controller mitsamt Routes geschrieben und fertig. Die Verbindung stimmt, Daten werden übertragen. Wieso das automatisch Ajax wird? Keine Ahnung.

Da ich nicht bewusst Ajax verwende (hab auch keinen Ajax-Call geschrieben oder so) kann ich natürlich auch keine Callback-Function setzen… wie auch?

Habe gerade alle Attribute der Form entfernt. Trotzdem is es noch ein Ajax Call.

Hallo,

das ist dann aber der Code: https://github.com/shopware/platform/blob/master/src/Storefront/Resources/views/storefront/element/cms-element-form/form-types/contact-form.html.twig . Und von dem seh ich in deinem HTML - Schnipsel nur wenig.

Hast du irgendetwas von den von mir genannten jetzt überhaupt mal gemacht? Die Attribute am Formular entfernt? save in save2 umbenannt? Mal die CSS - Klassen umbenannt? Wenn du nicht mal auf die callback - Funktion der Funktion kommst, die dein Formular absendet, würde ich empfehlen, die Funktionalität einfach selbst zu implementieren anstatt sie irgendwo her zu kopieren.

Grüße

Sebastian

hab ich doch geschrieben

  • ich habe die Attribute entfernt, es ändert nichts

  • ich habe NUR DAS HTML für das Formular kopiert. Kein Javascript, kein Ajax oder sonst irgendwas. Damit ich halt die CSS-Klassen hab für die Optik.

  • ich habe keine Funktion implementiert und auch nicht kopiert, die die Form absendet. Nix mit Ajax oder sonst was

 

genau den Code aus dem Link den du gepostet hast, hab ich auch als Basis genommen. Aber halt nur die HTML-Struktur für Eingabefelder, damit das Styling passt.

 

Ein umbenennen der Action in save2 bringt das selbe Ergebnis

 

EDIT:

Ursache ist offenbar die CSS-Klasse des DIVs außen rum. Die sorgt für automatische Übertragung der Form via Ajax wie es aussieht.

cms-element--form

 

Danke Sebastian für die Unterstützung!

Hallo,

deshalb meinte ich ja, du musst mal den ganzen Code zeigen. Hättest du irgendwo erwähnt, dass du die CSS-Klasse cms-element–form auch noch kopiert hast, hättest du hier https://github.com/shopware/platform/blob/master/src/Storefront/Resources/app/storefront/src/main.js#L148 gesehen, dass da ein JavaScript-Plugin dran hängt, das hier https://github.com/shopware/platform/blob/master/src/Storefront/Resources/app/storefront/src/plugin/forms/form-cms-handler.plugin.js#L69 das Formular über Ajax versendet, bei dem du hier https://github.com/shopware/platform/blob/master/src/Storefront/Resources/app/storefront/src/plugin/forms/form-cms-handler.plugin.js#L91 siehst, was an callbacks möglich wäre, wenn du die kopierte Funktionalität nutzt.

Grüße

Sebastian

dafür muss man wissen, dass irgendwelche Container außerhalb der eigentlichen Form irgendeine Relevanz haben … damit hatte ich nicht gerechnet, deshalb hatte ich nur die Form gepostet.

Danke trotzdem!

Hallo,

weniger kopieren, mehr selbst machen  . Aber kein Problem. An vielen CSS - Klassen oder - Attributen von Shopware hängen auch Funktionen, deshalb sollte man immer nur das Kopieren, was wirklich für die eigene Funktionalität nötig ist (und sich auch Gedanken machen, warum Sachen von allein funktionieren).

Grüße

Sebastian