Magento 2 Modulentwicklung - Teil 3: Controller und Actions

In diesem Teil unserer Blogserie über die Modulentwicklung in Magento 2 widmen wir uns den (Frontend) Controllern und Actions von Magento 2.

Controller steuern, einfach ausgedrückt, welcher Link auf welcher URL welche Aktionen durchführt und was dem Benutzer angezeigt wird.

Die Route für den Controller

Um in Magento 2 einen Controller anzulegen brauchen wir, genau wie in Magento 1.x, eine Route. Definiert wird diese in Magento 2 in der Datei etc/frontend/routes.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="helloworld" frontName="helloworld">
            <module name="Tudock_HelloWorld" />
        </route>
    </router>
</config>

In dieser Datei gibt es folgende Dinge zu beachten:

  • router_id für das Frontend ist standard.
  • route_id ist der Name unserer Route.
  • frontName ist der Pfad zu der Route, dort wird sie später erreichbar sein (<shop>.de/<route>/<controller>/<action>). route_id und frontName sollten identisch sein.
  • <module name="" /> muss den Vendor-Prefix und Namen unseres Moduls beinhalten.

Jetzt wo unsere Route angelegt ist, können wir den Controller erstellen.

Controller und Actions

Anders als in Magento 1.x gibt es keine Klasse für die Controller, die dann Methoden hat, welche ihre Actions repräsentieren. Stattdessen ist jede Action eine Klasse.

Controller sind nur noch durch einen Ordner repräsentiert (und optional durch eine abstrakte Klasse als Basis für jede Action).

Für einen Index Controller unserer helloworld Route brauchen wir also im Ordner Controller einen neuen Ordner Index. Alle Klassen in diesem Ordner sind die Actions unseres Index Controllers.

Für die Index-Action brauchen wir nun nur noch eine Klasse mit dem Dateipfad Controller/Index/Index.php anzulegen. Diese Action wird erreichbar sein unter <shop>.de/helloworld/index/index, wobei die beiden Index-Teile optional sind, genau wie in Magento 1.x.

<?php
namespace Tudock\HelloWorld\Controller\Index;

use \Magento\Framework\App\Action\Action;

class Index extends Action
{
	/** @var  \Magento\Framework\View\Result\Page */
	protected $resultPageFactory;
	
	/**
	 *
	 * Hier laden wir die Result\PageFactory.
	 * Diese wird benutzt um unsere darzustellen (siehe unten).
	 * Das Ganze geschieht via Dependency Injection, was genau
	 * das bedeutet und wie DI in Magento 2 funktioniert wird im
	 * nächsten Kapitel erklärt.
	 *
	 * @param \Magento\Framework\App\Action\Context $context
	 * @param \Magento\Framework\View\Result\Page $resultPageFactory
	 */
	public function __construct(\Magento\Framework\App\Action\Context $context,
		\Magento\Framework\View\Result\PageFactory $resultPageFactory) {
		$this->resultPageFactory = $resultPageFactory;
		parent::__construct($context);
	}

	/**
	 * Benutzt die geladene PageFactory um die Seite zu erzeugen.
	 * Die PageFactory wird das Layout laden und rendern.
	 * Das Layout und die Blöcke definieren wir im nächsten Schritt
	 *
	 * @return \Magento\Framework\View\Result\PageFactory
	 */
	public function execute() {
		return $this->resultPageFactory->create();
	}
}

Jede Action implementiert das Interface \Magento\Framework\App\Action\Action und ist im Namespace <Vendor>\<Modul>\Controller\<ControllerName>. Der Name der Klasse ist gleich dem Namen der Action.

Wie in den Kommentaren beschrieben, nutzt unsere execute-Methode (die ausgeführt wird, wenn die Action aufgerufen wird), die vorher via DependencyInjection geladene PageFactory. Eine Factory erstellt ein Objekt eines bestimmten Typs, in diesem Fall eine Page.

execute soll ein Objekt zurückgeben, das \Magento\Framework\Controller\ResultInterface implementiert. Page ist so ein Objekt.

Mehr über DependencyInjections und Factorys folgt in den nächsten Kapiteln dieser Blogserie.

Alle Klassen, die ResultInterface implementieren, können eine Seite rendern. Im Falle von Page wird das gesamte Layout für die Action geladen und dann gerendert.

Es gibt auch noch andere Klassen, die das ResultInterface implementieren und bspw. erlauben, rohen HTML Code zu rendern oder JSON-formatierte Daten für AJAX-Requests.

Layouts und Blöcke für die neue Action

Unser Controller lädt nun also das Layout für seine Seite und rendert es. Dieses Layout müssen wir jetzt noch definieren.

Wie genau das funktioniert, werde ich im letzten Kapitel der Blogserie erklären. Hier daher jetzt nur der Schnelldurchlauf:

Wir legen eine neue Layout-XML an. Diese muss zum Layout-Handle unserer Action passen, also helloworld_index_index.

view/frontend/layout/helloworld_index_index.xml:
[korrigiert am 24.08.2016, dank an Tobias für den Hinweis]

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Magento\Framework\View\Element\Template" name="hello-world" template="Tudock_HelloWorld::helloworld.phtml"/>
        </referenceContainer>
    </body>
</page>

Besonders ist hier im Vergleich zum letzten Kapitel, dass wir keinen eigenen Block benutzen, sondern den einfachen Template-Block, den Magento zur Verfügung stellt, um beliebige Templates zu rendern.

Wenn man einen Block rendert, der nicht im selben Modul liegt, so muss man für template ein Prefix zum Namen des Templates hinzufügen im Format Vendor_Modul::.

Unser Template (view/frontend/templates/helloworld.phtml) beinhaltet schlicht diesen Text:

<p>
	<?php echo __('Hello World') ?>!
</p>

Und die dazugehörige Übersetzung sieht so aus:

"Hello World", "Hallo Welt"

Testen

Wir können jetzt die neue Version unseres Moduls in den Shop installieren.

Dafür rufen wir unseren Shop auf und dann die URL /helloworld/index/index/.

Dort sollten wir jetzt den Text "Hallo Welt!" sehen.

Action verlinken

Aber was bringt uns eine neue Action, wenn niemand unsere tolle neue Seite sehen kann?

Als kleine Übung folgende Aufgabe:

Verlinke unsere neue Action in dem HelloProduct Block, den wir im letzten Teil angelegt haben. "Wie geht es dir?" soll auf die neue Action verlinken.

Die Lösung gibt es auf Github.

Tipp:
Die Klasse \Magento\Framework\View\Element\AbstractBlock hat eine Methode mit dem Namen getUrl. Sie funktioniert ähnlich wie in Magento 1.x .

Weiter geht es im nächsten Kapitel mit Dependency Injection und der Frage: "Was ist eigentlich mit Mage:: passiert?"

Autor: Kategorie: E-Commerce
Schlagwörter: Magento, Wissen, Magento2
YTo2OntzOjY6ImZldXNlciI7aTowO3M6MzoicGlkIjtpOjk2O3M6MzoiY2lkIjtpOjEwOTYxMjQyMzM7czo0OiJjb25mIjthOjEwOntzOjEwOiJzdG9yYWdlUGlkIjtpOjEyNDtzOjE0OiJleHRlcm5hbFByZWZpeCI7czoxMToidHhfbmV3c19waTEiO3M6MTM6IlVzZXJJbWFnZVNpemUiO2k6MTg7czo5OiJhZHZhbmNlZC4iO2E6MTp7czoyMToic2hvd0NvdW50Q29tbWVudFZpZXdzIjtpOjA7fXM6ODoic2hhcmluZy4iO2E6MTp7czoxMjoidXNlU2hhcmVJY29uIjtOO31zOjg6InJhdGluZ3MuIjthOjM6e3M6MTY6InJhdGluZ0ltYWdlV2lkdGgiO2k6MTE7czoxNjoicmV2aWV3SW1hZ2VXaWR0aCI7aToxNjtzOjg6Im1vZGVwbHVzIjtzOjQ6ImF1dG8iO31zOjY6InRoZW1lLiI7YTo3OntzOjI2OiJib3htb2RlbFRleHRhcmVhTGluZUhlaWdodCI7aTozMDtzOjI0OiJib3htb2RlbFRleHRhcmVhTmJyTGluZXMiO2k6NDtzOjE1OiJib3htb2RlbFNwYWNpbmciO2k6MTA7czoxODoiYm94bW9kZWxMaW5lSGVpZ2h0IjtpOjIwO3M6MTg6ImJveG1vZGVsTGFiZWxXaWR0aCI7aToxMzQ7czoyNjoiYm94bW9kZWxMYWJlbElucHV0UHJlc2VydmUiO2k6MTtzOjIyOiJib3htb2RlbElucHV0RmllbGRTaXplIjtpOjM1O31zOjE3OiJwcmVmaXhUb1RhYmxlTWFwLiI7YToxMDp7czoxNDoidHhfYWxidW0zeF9waTEiO3M6MTc6InR4X2FsYnVtM3hfaW1hZ2VzIjtzOjE1OiJ0eF9jb21tZXJjZV9waTEiO3M6MjA6InR4X2NvbW1lcmNlX3Byb2R1Y3RzIjtzOjEyOiJ0eF9pcmZhcV9waTEiO3M6MTA6InR4X2lyZmFxX3EiO3M6MTU6InR4X21pbmluZXdzX3BpMSI7czoxNjoidHhfbWluaW5ld3NfbmV3cyI7czo5OiJ0eF90dG5ld3MiO3M6NzoidHRfbmV3cyI7czoxMToidHRfcHJvZHVjdHMiO3M6MTE6InR0X3Byb2R1Y3RzIjtzOjI0OiJ0eF93ZWNzdGFmZmRpcmVjdG9yeV9waTEiO3M6MjU6InR4X3dlY3N0YWZmZGlyZWN0b3J5X2luZm8iO3M6MTI6InR4X2NvbW11bml0eSI7czo4OiJmZV91c2VycyI7czoxOToidHhfY3d0Y29tbXVuaXR5X3BpMSI7czo4OiJmZV91c2VycyI7czoxMToidHhfbmV3c19waTEiO3M6MjU6InR4X25ld3NfZG9tYWluX21vZGVsX25ld3MiO31zOjExOiJzaG93VWlkTWFwLiI7YTo1OntzOjk6InR4X3R0bmV3cyI7czo3OiJ0dF9uZXdzIjtzOjExOiJ0dF9wcm9kdWN0cyI7czo3OiJwcm9kdWN0IjtzOjEyOiJ0eF9jb21tdW5pdHkiO3M6NDoidXNlciI7czoxOToidHhfY3d0Y29tbXVuaXR5X3BpMSI7czoyNToiYWN0aW9uPWdldHZpZXdwcm9maWxlJnVpZCI7czoxMToidHhfbmV3c19waTEiO3M6NDoibmV3cyI7fXM6MTI6IlJlcXVpcmVkTWFyayI7czoxOiIqIjt9czo0OiJsYW5nIjtzOjI6ImRlIjtzOjM6InJlZiI7czoyOToidHhfbmV3c19kb21haW5fbW9kZWxfbmV3c18yMzMiO30%3DYTo0OntzOjQ6ImNvbmYiO2E6MzU6e3M6MTc6InVzZVdlYnBhZ2VQcmV2aWV3IjtzOjE6IjEiO3M6MjI6InVzZVdlYnBhZ2VWaWRlb1ByZXZpZXciO3M6MToiMSI7czoyMDoid2VicGFnZVByZXZpZXdIZWlnaHQiO3M6MjoiNzAiO3M6MjA6Im1heENoYXJzUHJldmlld1RpdGxlIjtzOjI6IjcwIjtzOjMxOiJ3ZWJwYWdlUHJldmlld0Rlc2NyaXB0aW9uTGVuZ3RoIjtzOjM6IjE2MCI7czozODoid2VicGFnZVByZXZpZXdEZXNjcmlwdGlvbk1pbmltYWxMZW5ndGgiO3M6MjoiNjAiO3M6Mjc6IndlYnBhZ2VQcmV2aWV3Q2FjaGVUaW1lUGFnZSI7czozOiIxODAiO3M6MzM6IndlYnBhZ2VQcmV2aWV3Q2FjaGVUaW1lVGVtcEltYWdlcyI7czoyOiI2MCI7czozMDoid2VicGFnZVByZXZpZXdDYWNoZUNsZWFyTWFudWFsIjtzOjE6IjAiO3M6Mjg6IndlYnBhZ2VQcmV2aWV3TnVtYmVyT2ZJbWFnZXMiO3M6MjoiMTAiO3M6Mzg6IndlYnBhZ2VQcmV2aWV3U2Nhbk1pbmltYWxJbWFnZUZpbGVTaXplIjtzOjQ6IjE1MDAiO3M6MzA6IndlYnBhZ2VQcmV2aWV3U2Nhbk1pbkltYWdlU2l6ZSI7czoyOiI0MCI7czozMDoid2VicGFnZVByZXZpZXdTY2FuTWF4SW1hZ2VTaXplIjtzOjM6IjQ1MCI7czoyOToid2VicGFnZVByZXZpZXdTY2FuTWluTG9nb1NpemUiO3M6MjoiMzAiO3M6MzE6IndlYnBhZ2VQcmV2aWV3U2Nhbk1heEltYWdlU2NhbnMiO3M6MjoiNDAiO3M6Mzg6IndlYnBhZ2VQcmV2aWV3U2Nhbk1heEltYWdlU2NhbnNGb3JMb2dvIjtzOjI6IjU1IjtzOjQwOiJ3ZWJwYWdlUHJldmlld1NjYW5NYXhIb3J6aXpvbnRhbFJlbGF0aW9uIjtzOjI6IjU7IjtzOjM3OiJ3ZWJwYWdlUHJldmlld1NjYW5tYXh2ZXJ0aWNhbHJlbGF0aW9uIjtzOjE6IjMiO3M6MzA6IndlYnBhZ2VQcmV2aWV3U2NhbkxvZ29QYXR0ZXJucyI7czoxMDoibG9nbyxjcmdodCI7czozODoid2VicGFnZVByZXZpZXdTY2FuRXhjbHVkZUltYWdlUGF0dGVybnMiO3M6NTc6InBpeGVsdHJhbnMsc3BhY2VyLHlvdXR1YmUscmNsb2dvcyx3aGl0ZSx0cmFuc3BhLGJnX3RlYXNlciI7czozODoid2VicGFnZVByZXZpZXdEZXNjcmlwdGlvblBvcnRpb25MZW5ndGgiO3M6MjoiNDAiO3M6MjU6IndlYnBhZ2VQcmV2aWV3Q3VybFRpbWVvdXQiO3M6NDoiNzAwMCI7czoxMjoidXNlUGljVXBsb2FkIjtzOjE6IjAiO3M6MTI6InVzZVBkZlVwbG9hZCI7czoxOiIwIjtzOjEzOiJwaWNVcGxvYWREaW1zIjtzOjM6IjEwMCI7czoxNjoicGljVXBsb2FkTWF4RGltWCI7czozOiI4MDAiO3M6MTY6InBpY1VwbG9hZE1heERpbVkiO3M6MzoiOTAwIjtzOjIyOiJwaWNVcGxvYWRNYXhEaW1XZWJwYWdlIjtzOjM6IjQ3MCI7czoyMzoicGljVXBsb2FkTWF4RGltWVdlYnBhZ2UiO3M6MzoiMzAwIjtzOjIwOiJwaWNVcGxvYWRNYXhmaWxlc2l6ZSI7czo0OiIyNTAwIjtzOjIwOiJwZGZVcGxvYWRNYXhmaWxlc2l6ZSI7czo0OiIzMDAwIjtzOjE4OiJzb3VuZGNsb3VkQ2xpZW50SUQiO3M6MDoiIjtzOjIyOiJzb3VuZGNsb3VkQ2xpZW50U2VjcmV0IjtzOjA6IiI7czoyMDoidXNlVG9wV2VicGFnZVByZXZpZXciO3M6MDoiIjtzOjI0OiJ0b3BXZWJwYWdlUHJldmlld1BpY3R1cmUiO2k6MDt9czoxMToiYXdhaXRnb29nbGUiO3M6Mjg6IldhcnRlIGF1ZiBBbnR3b3J0IHZvbiBHb29nbGUiO3M6ODoidHh0aW1hZ2UiO3M6MTM6IkJpbGQgZ2VmdW5kZW4iO3M6OToidHh0aW1hZ2VzIjtzOjE1OiJCaWxkZXIgZ2VmdW5kZW4iO30%3DYTowOnt9YTowOnt9YTo3OntzOjE2OiJjb21tZW50TGlzdEluZGV4IjthOjE6e3M6MzI6ImNpZHR4X25ld3NfZG9tYWluX21vZGVsX25ld3NfMjMzIjthOjE6e3M6MTA6InN0YXJ0SW5kZXgiO2k6MTU7fX1zOjE0OiJjb21tZW50c1BhZ2VJZCI7aTo5NjtzOjE2OiJjb21tZW50TGlzdENvdW50IjtpOjEwOTYxMjQyMzM7czoxMjoiYWN0aXZlbGFuZ2lkIjtpOjA7czoxNzoiY29tbWVudExpc3RSZWNvcmQiO3M6Mjk6InR4X25ld3NfZG9tYWluX21vZGVsX25ld3NfMjMzIjtzOjEyOiJmaW5kYW5jaG9yb2siO3M6MToiMCI7czoxMjoibmV3Y29tbWVudGlkIjtOO30%3D YTo1OntzOjExOiJleHRlcm5hbFVpZCI7aToyMzM7czoxMjoic2hvd1VpZFBhcmFtIjtzOjQ6Im5ld3MiO3M6MTY6ImZvcmVpZ25UYWJsZU5hbWUiO3M6MjU6InR4X25ld3NfZG9tYWluX21vZGVsX25ld3MiO3M6NToid2hlcmUiO3M6MTcwOiJhcHByb3ZlZD0xIEFORCBleHRlcm5hbF9yZWY9J3R4X25ld3NfZG9tYWluX21vZGVsX25ld3NfMjMzJyBBTkQgcGlkPTEyNCBBTkQgdHhfdG9jdG9jX2NvbW1lbnRzX2NvbW1lbnRzLmRlbGV0ZWQ9MCBBTkQgdHhfdG9jdG9jX2NvbW1lbnRzX2NvbW1lbnRzLmhpZGRlbj0wIEFORCBwYXJlbnR1aWQ9MCI7czoxMDoid2hlcmVfZHBjayI7czoxMzk6ImV4dGVybmFsX3JlZj0ndHhfbmV3c19kb21haW5fbW9kZWxfbmV3c18yMzMnIEFORCBwaWQ9MTI0IEFORCB0eF90b2N0b2NfY29tbWVudHNfY29tbWVudHMuZGVsZXRlZD0wIEFORCB0eF90b2N0b2NfY29tbWVudHNfY29tbWVudHMuaGlkZGVuPTAiO30%3D YToyOntpOjA7czoxNDk6IjxpbWcgc3JjPSIvdHlwbzNjb25mL2V4dC90b2N0b2NfY29tbWVudHMvcmVzL2Nzcy90aGVtZXMvdHVkb2NrL2ltZy9wcm9maWxlLnBuZyIgY2xhc3M9InR4LXRjLXVzZXJwaWMgdHgtdGMtdWltZ3NpemUiIHRpdGxlPSIiICBpZD0idHgtdGMtY3RzLWltZy0iIC8%2BIjtpOjk5OTk5O3M6MTUxOiI8aW1nIHNyYz0iL3R5cG8zY29uZi9leHQvdG9jdG9jX2NvbW1lbnRzL3Jlcy9jc3MvdGhlbWVzL3R1ZG9jay9pbWcvcHJvZmlsZWYucG5nIiBjbGFzcz0idHgtdGMtdXNlcnBpY2YgdHgtdGMtdWltZ3NpemUiIHRpdGxlPSIiICBpZD0idHgtdGMtY3RzLWltZy0iIC8%2BIjt9
4 Kommentare verfügbar
Bitte bestätigen Sie
Nein
Ja
Information
Ok
Vorschau wird geladen ...
* Pflichtfeld
Ihr Kommentar ist eine Antwort auf den folgenden Kommentar

Jan Rathmer () schrieb am 16.01.2018  

Hallo Tudock-Team,
erstmal vielen Dank für diese Blogserie, die mir den Einstieg in die Magento2-Entwicklung schon jetzt erheblich erleichtert hat.
Leider bekomme ich beim aufruf meines test-shops mit /helloworld/index/index nur einen 404 Not Found Error.
mehr anzeigen ...
Soweit ich das sehen kann, gibt es keinen Unterschied zwischen meinem Code und Github/der Blogserie.

Hat jemand eine Idee, wie ich der Sache nun Herr werden kann?

Viele Grüße

Antworten
Vorschau wird geladen ...
* Pflichtfeld

Jan Rathmer () schrieb am 16.01.2018  

Hat sich erledigt. Meine Ordnerstruktur passte nicht. Der "Controller" Ordner war nicht im Hauptverzeichnis, dann kann das natürlich auch nicht funktionieren. ;)

Antworten
Vorschau wird geladen ...
* Pflichtfeld

Tobias Eilers () schrieb am 24.08.2016  

Es muss nicht
view/frontend/layout/layout/helloworld_index_index.xml: heißen
sonder:
view/frontend/layout/helloworld_index_index.xml:
Sonst gibts ne weisse Seite.

Antworten
Vorschau wird geladen ...
* Pflichtfeld

Regine Voigt (https://www.tudock.de) schrieb am 24.08.2016  

Hallo Tobias,
vielen Dank für den Hinweis, da hat sich wohl ein Tippfehler eingeschlichen. Werden wir gleich korrigieren!
Schöne Grüße
Regine

Antworten
Vorschau wird geladen ...
* Pflichtfeld

Wir behalten uns vor, Kommentare zu löschen, beispielsweise wenn sich diese nicht auf den Beitrag beziehen, zur Eigenwerbung missbraucht werden, persönliche Daten anderer enthalten, diskriminieren, beleidigen oder Rechte verletzen.

Datenschutzhinweis: Wenn Sie einen Kommentar oder sonstigen Beitrag in unserem Blog hinterlassen, speichern wir neben Ihren Angaben Ihre IP-Adresse. Darüber hinaus können Sie die Beiträge und Kommentare unseres Blogs abonnieren. Das Kommentarabonnement können Sie jederzeit abbestellen. Weitere Informationen finden Sie in unserer Datenschutzerklärung.

E-Commerce & Webentwicklung: Wir realisieren und optimieren Internetprojekte. Unser Fachgebiet sind Onlineshops, Rich Internet Applications und anspruchsvolle Onlineauftritte. Über unsere Arbeit schreiben wir. Hier im Blog von TUDOCK.