Controller - ein einfaches Rechenbeispiel

Ich habe ein Problem, bei dem ich Hilfe benötige.

 

Ich habe mir einen eigenen Controller erstellt mit der dazugehörigen .tpl

Der Controller “Meincontroller” wird auch aufgerufen und ausgeführt.

In der gezeigten Shopseite steht nun “Bitte geben Sie eine Zahl ein:”

Jetzt allerdings kommt mein Problem:

Mein Controller sieht so aus:

 

View()->addTemplateDir(dirname( __FILE__ ) . "/../../Views/");
        }

        public function indexAction()
        {
		 $this->View()->loadTemplate("frontend/index.tpl");	
		 
		}
		
	public function addAction(Enlight_Controller_ActionEventArgs $args)
	{
		$request = $this->Request();
		$view = $this->View();
		$myNumber = (int)$request->getParam('myNumber', 0);
		$result = $myNumber + 10;
		$view->assign('result', $result);
	}
}

und die .tpl:

{extends file="frontend/index/index.tpl"}
{block name="frontend_index_content"}


    Rechenbeispiel


Bitte geben Sie eine Zahl ein






Ergebnis abrufen



Ergebnis: {$result} 
{/block}

gestyled ist erst einmal nichts.

Im Moment versuche ich eine relativ einfache Aufgabe zu lösen:

Ich möchte eine Eingabe in dem Eingabefeld machen - z.B.: 20

Dann soll, wenn der Button angeklickt wird, die addAction im Controller aufgerufen werden und zu der eingegebenen Zahl 10 hinzuaddiert - und natürlich angezeigt - werden.

Klicke ich aber auf den Button, dann steht in der URL: /Meincontroller/add - und ich erhalte eine weiße Seite.

Was mache ich bitte falsch?

Ich habe auch das Entwicklerhandbuch von Herrn Nögel, doch leider gibt es dort auch keine Lösung.

Selbst die vorhandenen Controller von SW habe ich mir angeschaut, doch bei mir wird keine Berechnung durchgeführt.

BITTE kann mir jemand mal helfen - vieleicht sogar Herr Nögel.

Ich würde mich SEHR freuen, wenn ich eine wegweisende Antwort erhalten würde.

Wirklich niemand ???

Muß da etwa noch jQuery eingepflegt werden?

Oder warum kann ich den Post nicht im Controller verarbeiten und an die .tpl zurückgeben?

 

Hallo @hoppler‍,

zuerst einmal zu der weißen Seite:
Du rufst über den von dir gewählten Weg die URL: meinShop,de/meinController/add auf.
In diesem Fall erwartet Shopware eine Datei namens add.tpl, anlehnend an den Namen deiner Action, im Theme-Ordner „mein_controller“.
Da du diese Datei wohl nicht besitzt, bekommst du eine weiße Seite.

Du hast nun im Prinzip zwei Möglichkeiten:

  1. Du legst eine add.tpl in dem o.g. Ordner an und leitest diesen von deiner index.tpl ab - dort bekommst du dann das Ergebnis angezeigt. Dies bedeutet aber immer einen Reload der Seite und ist eher semi-schön.

  2. Du baust das Ganze nicht mit einem HTML-Form, welches, wie im Punkt 1 genannt, eine neue Seite öffnet beim Ausführen des Formulars, sondern mit einem sogenannten AJAX-Request. 
    Dabei kann dir durchaus jQuery behilflich sein.
    In diesem Fall sendest du deinen AJAX-Request ebenfalls an deine addAction, müsstest in der AddAction jedoch folgende Zeile ergänzen:

    $this->container->get(‚front‘)->Plugins()->ViewRenderer()->setNoRender();

Diese Zeile sorgt dafür, dass deine Action kein eigenes Template zu laden versucht.
Dadurch würde aber auch die Zeile „$view->assign()…“ an Sinn verlieren.
Hier könntest du am Einfachsten (es gibt auch elegantere Wege) eben dein Ergebnis per PHP-Funktion json_encode() JSON enkodieren und dann per bspw. „echo“ ausgeben, sodass der AJAX-Request die Response verarbeiten kann.

Bin leider gerade etwas im Zeitdruck um dazu mehr ins Detail zu gehen, aber die Grundidee hilft dir ggf. schon mit ein bisschen Nachforschung.
Alternativ schaue ich morgen nochmal drüber und versuche das Ganze mit konkreten Beispielen zu schmücken.

Lieben Gruß,
Patrick  Shopware

Hallo Patrick,

 

erst einmal danke ich Dir sehr für Deine Antwort.

Da ich versuchen möchte zu VERSTEHEN wie etwas funktioniert, so denke ich, war Deine Antwort schon einmal hilfreich.

Ich werde es erst einmal über einen reload machen - stimmt ist etwas unschön. Aber später kann ich das ja über XHR, also über einen ajax-request machen.

Und das geht ja über jquery, wie ich denke.

Jetzt werde ich erst einmal „basteln“ und dann berichten.

L.G.

 

Guten Morgen Patrick,

irgendwie steige ich nicht durch.

 

Ich habe fast die ganze Nacht damit verbracht das Ergebnis meiner Rechenaufgabe angezeigt zu bekommen - leider ohne Erfolg.

Damit es verständlicher wird:

Verzeichnisstrucktur:

\Mein_Plugin                                       -     hier ist die Bootstrap

\Mein_Plugin\Controller

\Mein_Plugin\Controller\frontend       -     hier ist der Controller: Meincontroller.php

\Mein_Plugin\Views\frontend             -     hier liegen die index.tpl und die add.tpl

Controller:

View()->addTemplateDir(dirname( __FILE__ ) . "/../../Views/");
        }

        public function indexAction()
        {
			
		 $this->View()->loadTemplate("frontend/index.tpl");	
		}
		
		public function addAction(Enlight_Controller_ActionEventArgs $args)
		{
				

			$request = $this->Request();
			$view = $this->View();
			$myNumber = (int)$request->getParam('myNumber', 0);
			$result = $myNumber + 10;
			$view->assign('result', $result);
			$this->View()->loadTemplate("frontend/add.tpl");	
		}
}

und hier die .index.tpl:

 {extends file="frontend/index/index.tpl"}
{block name="frontend_index_content"}


    {s name='SitemapHeader'} Rechenbeispiel{/s}


Bitte geben Sie eine Zahl ein



	 
	 
        
		Rechnen
        
    
	
{/block}

und hier meine add.tpl:

 {extends file="frontend/index/index.tpl"}
{block name="frontend_index_content" append}

Ergebnis der Berechnung: {$result} 

{/block}

Habe die add.tpl auch in das Verzeichnis:

\Mein_Plugin\Controller\frontend

kopiert.

Aber leider funktioniert immer noch nichts. Immer wieder werde ich auf: /Mein_Shop/Meincontroller/add weitergeleitet wo eine leere Seite ist.

So langsam verzweifel ich etwas.

Es kann doch nicht so schwer sein. Und ich kann mir vorstellen dass auch andere sich für diese Problematik interessieren.

 

L.G.

Hoppler

Moin @hoppler‍,

du hast da ein paar Sachen durcheinander geworfen. :slight_smile:

  1. Dein Controller sollte hier liegen: \Mein_Plugin\Controllers\MeinController.php  oder  \Mein_Plugin\Controllers<u>Frontend
    Warum das? Ist einfach eine Konvention - musst du jetzt aber nicht zwingend beachten und ist für die Funktionalität deiner Anwendung erstmal nicht wichtig.

  2. Deine Template Dateien sollten alle  hier liegen: \Mein_Plugin\Views\frontend\mein_controller\
    Warum?
    Shopware Frontend Controller besitzen eine Art Template Autoloading - das heißt, dass eine Controller-Action eines Frontend Controllers immer auch von allein nach einem Template sucht.
    Die Suche nach dem passenden Template findet unter folgenden Gesichtspunkten statt:

  • Es werden alle Template-Verzeichnisse in Anbetracht gezogen (Deswegen fügst du in der init-Methode auch per „addTemplateDir“ deinen eigenen Views Ordner hinzu)
  • Er sucht innerhalb der Template-Verzeichnisse nach dem richtigen Module, in diesem Fall nach einem Ordner namens  frontend/ , weil du einen Frontend-Controller hast. Wäre es ein Backend Controller, würde er stattdessen nach einem Ordner „backend/“ suchen.
  • Anschließend erwartet er einen Ordner, der so benannt ist wie dein Controller, bloß in im sogenannten SnakeCase. Das bedeutet, dass aus deinem Controller Namen „MeinController“ anschließend „mein_controller“ wird. Er sucht also nach einem Ordner  mein_controller/.
  • Zu guter Letzt sucht er nach einer Template Datei, die nach deiner Action benannt ist. In deinem Fall eine addAction. Er lässt das „Action“ weg und sucht somit nach einer  add.tpl

Zusammenfassend: Die Templates für deine indexAction / addAction müssen hier liegen: \MeinPlugin\Views\frontend\mein_controller\ und dort dann jeweils  index.tpl  und  add.tpl.

Soweit erstmal klar? :slight_smile:

Da du dich nun auf das Template Autoloading stützt, kannst du deine indexAction auch löschen.
Warum das jetzt? Alles, was deine IndexAction bislang macht, ist ein Template manuell  zu laden. Brauchst du jetzt ja nicht mehr, wenn du das Autoloading für die Templates nutzt.  Thumb-Up
Ist das verständlich?

Dann dürfte deine addAction auch vernünftig funktionieren und ein vernünftiges Template anzeigen.
 

Immer wieder werde ich auf: /Mein_Shop/Meincontroller/add weitergeleitet wo eine leere Seite ist.

Bis auf die leere Seite, die mit o.g. Weg auch nicht mehr weiß sein dürfte, ist die Weiterleitung als Solches ja auch erstmal korrekt. :slight_smile:

Ich hoffe damit kommst du erstmal weiter.

Gruß,
Patrck  Shopware

Hallo Patrick,

nun, das nenne ich mal eine tolle Erklärung!!! Thumb-Up

Ach ja, mein Fehler, der Controller liegt natürlich in /Controllers/Frontend - hatte falsch kopiert. Blush

Jedenfalls Danke ich Dir für den Weg zur Lösung und nicht für die Lösung als solches, so mit fertigem Code.

Denn nur auf diese Art und Weise kann man lernen und verstehen warum etwas funktioniert.

Jetzt werde ich mich wieder frohen Mutes an die Arbeit machen und werde selbstverständlich berichten.

L.G.

Hoppler

Hallo Patrick,

nachfolgendes ist etwas verwirrend:

Zusammenfassend: Die Templates für deine indexAction / addAction müssen hier liegen: \ MeinController \Views\frontend\mein_controller\ und dort dann jeweils  index.tpl  und  add.tpl.

Soll *\MeinController* das Pluginverzeichnis sein?

Was habe ich nun anders gemacht?

Ich habe die Ordnerstrucktur geändert:

/Mein_Plugin/Bootstrap.php

/Mein_Plugin/Controllers/Frontend/MeinController.php

/Mein_Plugin/Views/frontend/mein_controller/index.tpl

/Mein_Plugin/Views/frontend/mein_controller/add.tpl

 

Hier noch einmal der Controller:

View()->addTemplateDir(dirname( __FILE__ ) . "/../../Views/");
        }

		 public function indexAction()
        {
		 $this->View()->loadTemplate("frontend/mein_controller/index.tpl");	
		}
		
		public function addAction(Enlight_Controller_ActionEventArgs $args)
		{
			$request = $this->Request();
			$view = $this->View();
			$myNumber = (int)$request->getParam('myNumber', 0);
			$result = $myNumber + 10;
			$view->assign('result', $result);
		}
}

Lasse ich die indexAction weg, geht gar nichts mehr - es wird nur die Startseite angezeigt.

index.tpl:

{extends file="frontend/index/index.tpl"}
{block name="frontend_index_content"}


    {s name='SitemapHeader'} Rechenbeispiel{/s}


Bitte geben Sie eine Zahl ein



	 
	 
        
		Rechnen
        
    

{/block}

und meine add.tpl:

{block name="frontend_index_content" append}

Ergebnis: {$result} 

{/block}

 

Wenn ich mir nun den Aufruf des Controllers anschaue, dann habe ich jetzt einen Fehler:

GET http://localhost/sh530/meincontroller                [HTTP/1.0 500 Internal Server Error 2949ms]

Es wird mir zwar das Rechenbeispiel angezeigt und ich kann auch ein Ergebnis anfordern, doch wenn ich das Ergebnis holen will, dann kommt:

Invalides Formular-Token!

Die Aktion konnte aufgrund eines invaliden Formular-Tokens nicht durchgeführt werden.
Ein neues Token wurde bereits generiert.

Bitte gehen Sie in Ihrem Browser eine Seite zurück und starten die Aktion erneut.

Zurück zur vorherigen Seite

Die Adresse im Browser:

http://localhost/sh530/meincontroller/add

Der Fehler in der Konsole wird auch noch angezeigt.

 

Was mich auch wundert:

Der Controller wird mit GET aufgerufen, doch die Daten (die Zahl) werden mit POST übermittelt - liegt da eventuell der Fehler?

 

Es tut mir Leid, dass ich anfange zu nerven - ich möchte doch nur das es funktioniert und ich endlich darauf aufbauen kann.

 

Moin @hoppler‍,

entschuldige, da ist mir ein Fehler unterlaufen. Das hätte natürlich ‚MeinPluginVerzeichnis‘ heißen sollen - aber das scheinst du ja schon richtig gemacht zu haben! :slight_smile:

Zu deinen Fehlern:
Da sehe ich jetzt so spontan das Problem auch noch nicht.
Hast du die Möglichkeit mir das Plugin irgendwo hochzuladen und dann per PN zu schicken?
Dann kann ich es mir mal im Detail anschauen und auch diese Fragen beantworten, ohne dir die konkrete Lösung zu nennen.  Wink

Gruß,
Patrick  Shopware

Hallo Patrick,

habe noch etwas experimentiert, doch es funktioniert immer noch nicht.

Habe Dir das Plugin per PN gesendet.

 

L.G.

Hoppler

Moin @hoppler‍ !

Ich habe mir gerade das Plugin einmal angesehen.
Danke dir für die Zusendung.

Also, den 500 Fehler bekommst du aus einem unscheinbaren Grund:
In deiner index.tpl verlinkst du deinen Frontend Controller komplett kleingeschrieben, also so:

{url controller='meincontroller' action='add'}

Das hat zur Folge, dass er auch die Url so kleingeschrieben aufruft:
meinShop.de/meincontroller/add

Warum ist das nun ein Problem?
Falls du dich erinnerst, habe ich dir gesagt, dass du deine Template Dateien  index.tpl  und  add.tpl  in dem Ordner  mein_controller  ablegen sollst.
Die Begründung war, weil Shopware aus MeinController, also aus der Camel-Case Schreibweise, die Worte auftrennt und sie per Snake-Case verbindet.
Somit würde aus MeinController => mein_controller werden.
Da du aber alles klein geschrieben hast, kann er die Worte nicht unterscheiden und erwartet dann die o.g. Template Dateien in dem Ordner Views/frontend/meincontroller.

Die Lösung: Den Aufruf deines Controllers in deinem Template auch per CamelCase geschehen lassen. :slight_smile:

Darüber hinaus:

  1. Lass deine indexAction einfach komplett leer - das funktioniert auch. Das Template musst du da nicht händisch laden

  2.  In deiner add.tpl hast nur einen Block, der appenden soll. Das funktioniert nicht.
    Warum?
    Wenn du an einem Block ein „append“ oder „prepend“ anhängst, implizierst du Smarty ja, dass es einen „Original“-Block gibt, an den du dich hängen willst.
    Nur woher kommt dieser originale Block?
    In deiner ersten Zeile fehlt also ein „extends“, so wie du das schon in der index.tpl gemacht hast.
    Also:

    {extends file=„parent:frontend/index/index.tpl“}

    {block name=„frontend_index_content“ append}

        Rechenbeispiel
    
    
    Ergebnis: {$result} 
    

    {/block}

Hilft dir das weiter?

Gruß,
Patrick  Shopware

Hallo Patrick,

 

erst einmal ein ganz dickes Lob für Deine Hilfe!!! Thumb-Up

Ich habe verstanden was Du mir mitgeteilt hast - war ja auch sehr gut erklärt.

Die indexAction habe ich leer gelassen - was auch funktioniert. Super Tip!

Den Aufruf des Controllers habe ich geändert:

Es wird auch jetzt die URL /MeinController/add aufgerufen und angezeigt.

Doch ich erhalte die Meldung:

Invalides Formular-Token!

Die Aktion konnte aufgrund eines invaliden Formular-Tokens nicht durchgeführt werden.
Ein neues Token wurde bereits generiert.

Bitte gehen Sie in Ihrem Browser eine Seite zurück und starten die Aktion erneut.

Zurück zur vorherigen Seite

Ich habe versucht /MeinController/add manuel aufzurufen, was jedoch nicht geht - weiße Seite.

Liegt bestimmt an Restriktionen von Seiten Shopware, da man ja sonst den Checkout Controller aufrufen könnte, mit der Funktion dass bezahlt wurde - nur ein Beispiel.

Ich habe jedoch den Verdacht dass die add.tpl gar nicht geladen wird.

Daher versuchte ich folgendes:

public function addAction(Enlight_Controller_ActionEventArgs $args)
		{
			 
			$request = $this->Request();
			$view = $this->View();
			$myNumber = (int)$request->getParam('myNumber', 0);
			$result = $myNumber + 10;
			$view->assign('result', $result);
			$this->View()->loadTemplate("frontend/mein_controller/add.tpl");	
		}

Aber auch das fruchtet nicht.

Vieleicht liegt es ja an meiner Shopware Version?

Ich benutze Shopware 5.3.2, welches mit xampp läuft Also auf dem localhost.

 

Wie ich geschrieben habe, möchte ich verstehen warum etwas funktioniert. Nur ist es frustrierend, wenn man trotz toller Hilfe immer wieder vor Problemen steht, die eingentlich nicht sein dürften.

Warum habe ich den Token Fehler und warum wird mir das Ergebnis nicht angezeigt???

 

Moin @hoppler‍,

das Problem mit dem Token kann ich bei mir definitiv nicht nachstellen.
Schau’ mal bitte, ob deine  addAction  in deinem Controller einen Parameter bekommt - das darf nämlich nicht sein.

Die weiße Seite spricht auch dafür, dass du weiterhin die add.tpl nicht von der index.tpl ableitest.
So müsste deine add.tpl ausschauen:

 

{extends file="parent:frontend/index/index.tpl"}

{block name="frontend_index_content" append}
    
        Rechenbeispiel
    
    Ergebnis: {$result} 
{/block}

Stimmt das wirklich überein?
Besonders die erste Zeile ist da sehr wichtig.

Lieben Gruß,
Patrick  Shopware

Hallo Patrick,

nun, ich habe es endlich hinbekommen, dass das Ergebnis angezeigt wird.

Was habe ich gemacht?

public function addAction(Enlight_Controller_ActionEventArgs $args)
		{
			 
			$request = $this->Request();
			$view = $this->View();
			$myNumber = (int)$request->getParam('myNumber', 0);
			$result = $myNumber + 10;
			$view->assign('result', $result);
			$this->View()->loadTemplate("frontend/mein_controller/add.tpl");	
		}

Die Funktion oben addiert 10 zu meiner Eingabe, WENN ich die Funktion ändere:

public function addAction() {		 
			$request = $this->Request();
			$view = $this->View();
			$myNumber = (int)$request->getParam('myNumber', 0);
			$result = $myNumber + 10;
			$view->assign('result', $result);
		            }

Ich habe die Parameter in der Klammer weggelassen UND ich mußte in der Config.php den CSRF-Token deaktivieren.

Auch habe ich das „loadTemplate“ weggelassen. Wie Du geschrieben hast, ist es ja nicht notwendig - guter Tip! Funktioniert bestens.

Allerdings weiß ich im Moment nicht wie ich das mit dem Token in mein Plugin kriegen kann, dass es auch funktioniert, wenn der CSRF-Token nicht deaktiviert ist.

Könntest Du mir da bitte noch einmal helfen?

L.G.

 

 

Moin @hoppler‍,

der CSRF Token dürfte da normalerweise echt kein Problem darstellen - ich konnte diesen Fehler in meinem System auch nie nachstellen.
Normalerweise sorgt ein Javascript Script dafür, dass dein Formular automatisch mit einem validen CSRF-Token beschmückt wird.

Versuch’ mal deinen ganzen Cache zu leeren (inklusive Theme kompilieren) und leere alle Cookies aus deinem Browser - möglicherweise hast du da noch defekte Stände gespeichert.

Gruß,
Patrick  Shopware

Hallo Patrick,

ich habe jetzt alles mögliche versucht, doch nur wenn ich den CSRF-Token in der Config deaktiviert funktioniert die Berechnung.

Alle Caches wurden gelöscht.

So sieht es aus, wenn ich den Controller aufrufe:

 

Wenn ich dann auf Berechenen klicke - und der CSRF-Token ist aktiviert, dann kommt das:

Habe Dir das Plugin per PN zugeschickt.

 

Benutze SW-Version 5.2.27 und 5.3.2

 

L.G.

 

Hallo Patrick,

ich habe die Lösung gefunden !

Folgendes mußte ich im Controller interieren:

use Shopware\Components\CSRFWhitelistAware;

class Shopware_Controllers_Frontend_MeinController extends Enlight_Controller_Action implements CSRFWhitelistAware

 

und dann die gewünschte Action - hier die Index, über:

public function getWhitelistedCSRFActions()
    {
        return [
            'index'
        ];
    }

aufrufen.

Und siehe da, es funktioniert!!! Smile

 

Ganz, ganz lieben Dank für Deine Hilfe und Deine Geduld!!! Thumb-Up

 

L.G.

O.K.,

eine Frage könntest Du mir bitte noch beantworten:

Wie kann ich das nun so machen das die Seite nicht neu lädt?

Über ein Ajax-Request?

Wäre toll, wenn Du mir da helfen könntest.

L.G.

Moin @hoppler‍,

freut mich, dass du eine Lösung gefunden hast.

Ich möchte aber gern Folgendes hinzufügen:
Was du nun machst, ist deine indexAction von der CSRF-Token Validierung auszuschließen.
Im Prinzip behebst du das Symptom des Problems, nicht aber die Ursache.
Diese ist jedoch mit gutem Grund vorhanden - daher wäre dies zwar eine Lösung, du würdest damit aber potentiell eine Sicherheitslücke einbauen.
In diesem Beispiel wäre das so nicht weiter kritisch, weil deine indexAction nichts Gefährliches ausführt.

Solltest du jedoch irgendwann soweit sein, dass du echte Plugins für den Store oder für Kunden in Produktion entwirfst, wo ggf. mit sensiblen Daten umgegangen werden muss, solltest du diese Lösung nicht wählen.

Gruß,
Patrick  Shopware

Hallo Patrick,

Du hast natürlich recht, dass dies keine elegante Lösung ist.

Ich habe mir den Developer Guide angeschaut. Von dort habe ich auch die „Lösung“.

Was ich allerdings nicht verstehe ist, dass bei mir, wenn ich das Plugin ohne das Whitelisting ausführe, der Controller aufgerufen wird und auch die Eingabe der Zahlen verlangt.

Jedoch wenn ich auf „Rechnen“ klicke und die Daten per Post an den Controller zurücksende, wegen der Berechnung, dann kommt dieser Token Fehler.

Ich habe ja nur einen Controller und ‚noch‘ kein JS eingebunden.

Wie bitte mache ich es richtig, das das Plugin richtig, auch mit dem Token, läuft.

Muß ich in der:

auch irgendwie den CSRF Token mit hineinnehmen?

Könntest Du Dir bitte das Plugin, welches ich als PN geschickt habe, anschauen und mir sagen was ich machen muß das ich keine Probleme mehr mit dem Token bekomme?

L.G.

Hoppler