RahmspinatRahmspinat MemberComments: 36 Received thanks: 2 Member since: November 2012 edited November 23

Hallo,

ich würde gerne per AJAX auf den Newsletter Controller zugreifen, ohne dass der User direkt auf die Newsletter-Seite weitergeleitet wird. Ich möchte damit ermöglichen, dass sich User ohne die Newsletter-Seite und ohne zusätzliches Laden der kompletten Seite registrieren können.

Meine Idee war folgende:

Ich schreibe einen Plugin mit einem Controller der in etwa wie folgt aussieht:

<?php
class Shopware_Controllers_Frontend_NewsletterAjax extends Enlight_Controller_Action
{
    public function indexAction()
    {
        $this->Front()->Plugins()->ViewRenderer()->setNoRender();

        // Hier möchte ich den Aufruf zur Registrierung direkt an den Newsletter-Controller 
        // weiterleiten, so das ich nur im Ergebnis ($result) schauen muss, ob die Registrierung 
        // erfolgreich ist oder nicht
        $result = $this->forward('index', 'newsletter', 'frontend', $this->Request()->getParams());

        //bei $result erhalte ich leider nur NULL als Ausgabe
        echo '<pre>';
        var_dump($result);
        echo '</pre>';
        die();

        // Hier will ich das ergebnis per JSON zurückgeben um später eine Bestätigung anzeigen zu 
        // können, ob die Registrierung erfolgreich war oder nicht
        $this->Response()->setBody(
            json_encode(
                [
                    //Hier das Ergebnis ob die Registierung erfolgreich war oder nicht
                    'info1' => 123,
                    'info2' => 333
                ]
            )
        );
    }
}

1. Warum funktioniert mit $this->forward so scheinbar nicht?

2. Was haltet ihr von diesem Weg, was wäre aus eurer Sicht die bessere Alternative?

Answers

  • brettvormkoppbrettvormkopp MemberComments: 2032 Received thanks: 397 Member since: March 2013

    Das ist eine schöne Idee. ich kann dir nicht genaueres zum newsletter controller sagen, aber vll helfen dir ein paar infos.

    • Ich würde aber erstmal bei den params checken ob es X und Y parameter sind und nicht jeden durchlassen.
    • Anschliessend den newsletter Controller anrufen
    • Ich glaub norender muss nicht sein wenn keine themedatei vorhanden ist juckts nicht.
    • und zum schluss echo json_encode(array("info1" => 123. "info2" => 333)); statt $this->......
    • das die() kommt dann ganz zum schluss. sonst wird ja das json_encode nicht ausgeführt
    Thanked by 1Rahmspinat
  • RahmspinatRahmspinat MemberComments: 36 Received thanks: 2 edited November 19 Member since: November 2012

    Danke für deine Antwort.

    • Ich würde aber erstmal bei den params checken ob es X und Y parameter sind und nicht jeden durchlassen.
      • Das sollte nur für ein schnelles Ergebnis sorgen, du hast recht, in der Endform werde ich da nur das nötigste durchlassen
    • Anschliessend den newsletter Controller anrufen
      • Hier habe ich meine Probleme. Wie funktioniert das? mein $this->forward(...) liefert leider nur NULL, woran kann das liegen? Wie würdest du den einen anderen Controller aufrufen?
    • Ich glaub norender muss nicht sein wenn keine themedatei vorhanden ist juckts nicht.
    • und zum schluss echo json_encode(array("info1" => 123. "info2" => 333)); statt $this->......
    • das die() kommt dann ganz zum schluss. sonst wird ja das json_encode nicht ausgeführt
      • Das die() war nur dafür da, dass ich erstmal sehe, was ich im $result habe und leider steht da nur "null" drin. Ich würde das die() auch ungern drin lassen, das sollte auch kein Problem sein
  • RahmspinatRahmspinat MemberComments: 36 Received thanks: 2 Member since: November 2012

    Ich habe gerade festgestellt das $this->forward(...) gar keinen return Wert zurück gibt. Daher ist ja klar, dass ich keine Antwort auf die Eintragung erhalte. Wenn ich keine Bestätigung habe, kann ich dem User leider nicht sagen, dass er erfolgreich eingetragen wurde.

    Frageg ist wie eine Alternative aussieht?

  • RahmspinatRahmspinat MemberComments: 36 Received thanks: 2 edited November 20 Member since: November 2012

    Ich habe mich jetzt gegen einen eigenen Controller entschieden und werde mit einem Event vom Newsletter-Controller arbeiten.

    Wenn der Controller mit seiner Arbeit durch ist, sag ich ihm dass er die View nicht rendern und stattdessen JSON ausgeben soll. 

    if($this->isAjaxRequest($request)) {

    $controller->Front()->Plugins()->ViewRenderer()->setNoRender();

     

    Über die $args des Events kann ich mir 1. ausgeben lassen ob die Anmeldung des Users erfolgreich war und 2. ob es sich um einen "ajaxRequest" handelt. So kann ich das View-Rendern nur dann deaktivieren wenn es wirklich einen ajax-Aufruf gab. In das Form habe ich mir dafür ein hidden input-Field gepackt mit dem namen "ajax-newsletter".

     

    Mein Problem war bis eben noch, dass ich kein Captcha habe. Dafür habe ich mir diesen Block aus der newsletter.tpl kopiert:

    {* Captcha *}
                                {block name="frontend_newsletter_form_captcha"}
                                    {if !({config name=noCaptchaAfterLogin} && $sUserLoggedIn)}
                                        {$newsletterCaptchaName = {config name=newsletterCaptcha}}
                                        <div class="newsletter--captcha-form">
                                            {if $newsletterCaptchaName === 'legacy'}
                                                <div class="newsletter--captcha">
    
                                                    {* Deferred loading of the captcha image *}
                                                    {block name='frontend_newsletter_form_captcha_placeholder'}
                                                        <div class="captcha--placeholder" {if $sErrorFlag.sCaptcha}
                                                             data-hasError="true"{/if}
                                                             data-src="{url module=widgets controller=Captcha action=refreshCaptcha}"
                                                             data-autoload="true">
                                                        </div>
                                                    {/block}
    
                                                    {block name='frontend_newsletter_form_captcha_label'}
                                                        <strong class="captcha--notice">{s name="SupportLabelCaptcha" namespace="frontend/forms/elements"}{/s}</strong>
                                                    {/block}
    
                                                    {block name='frontend_newsletter_form_captcha_code'}
                                                        <div class="captcha--code">
                                                            <input type="text" name="sCaptcha" class="newsletter--field{if $sErrorFlag.sCaptcha} has--error{/if}" required="required" aria-required="true" />
                                                        </div>
                                                    {/block}
                                                </div>
                                            {else}
                                                {$captchaName = $newsletterCaptchaName}
                                                {$captchaHasError = isset($sErrorFlag) && count($sErrorFlag) > 0}
                                                {include file="widgets/captcha/custom_captcha.tpl" captchaName=$captchaName captchaHasError=$captchaHasError}
                                            {/if}
                                        </div>
                                    {/if}
                                {/block}

     

    Wenn ich jetzt mit einem Form-Data-Faker arbeite und ihn automatisch die Daten ausfüllen lasse, dann trifft er auf den konfigurierten Honeypot und wird aussortiert.

     

    Wenn ich mir das so korrekt denke, dann sollten doch alle anderen Plugins etc. kein Problem mit meinem Newsletter-Plugin haben oder? Ich habe mir extra das 'Enlight_Controller_Action_PostDispatchSecure_Frontend_Newsletter' Event geschnappt und verändere nur die view.

     

    Was sagt ihr dazu?

  • RahmspinatRahmspinat MemberComments: 36 Received thanks: 2 Member since: November 2012

    Jetzt habe ich leider ein anderes Problem.

    Wenn ich den Newsletter-Endpoint anspreche, dann hat dieser angeblich keine Werte erhalten. Im Request-Objekt sind alle Daten enthalten die ich geschickt habe. In der Newsletter.php werden die Daten aber wie folgt z.B. ausgelesen:

            if (!isset(Shopware()->System()->_POST['newsletter'])) {
                return;
            }
    
            if (Shopware()->System()->_POST['subscribeToNewsletter'] != 1) {
                // Unsubscribe user
                $this->View()->assign('sStatus', Shopware()->Modules()->Admin()->sNewsletterSubscription(Shopware()->System()->_POST['newsletter'], true));
    
                $session = $this->container->get('session');
                if ($session->offsetExists('sNewsletter')) {
                    $session->offsetSet('sNewsletter', false);
                }
    
                return;
            }

    Leider ist die Variable: Shopware()->System()->_POST leer. Bei einem normalen Aufruf der Seite und das anmelden über die Standard /newsletter - Seite, sind diese Variablen befüllt.

    Warum sind diesen Variablen leer?

     

    Ich habe dafür einen "fix" in mein Plugin aufgenommen wo ich mit einem PreDispatch_Frontend_Newsletter folgende Variablen setze:

    $existingPostVars = Shopware()->System()->_POST->toArray();
    
                $params = [
                    'subscribeToNewsletter' => $request->getParam('subscribeToNewsletter'),
                    'newsletter' => $request->getParam('newsletter'),
                    'ajax-request' => $request->getParam('ajax-request'),
                    'first_name_confirmation' => $request->getParam('first_name_confirmation'),
                    'captchaName' => $request->getParam('captchaName'),
                    '__csrf_token' => $request->getParam('__csrf_token'),
                    'module' => $request->getParam('module'),
                    'controller' => $request->getParam('controller'),
                    'action' => $request->getParam('action'),
                ];
    
                $params = array_merge($params, $existingPostVars);
    
                Shopware()->System()->__set('_POST', $params);

    Das fühlt sich wie ein hack und etwas dirty an... Auf jeden Fall habe ich jetzt eine "Newsletter-Api"

     

    Was sagt ihr zu dem Fix und wisst ihr warum keine Daten aus 'Shopware()->System()->_POST->toArray()' kommen, wenn ich diese per Rest-Client aufrufe?

Sign In or Register to comment.