Route und Controller

Erstelle deine erste Seite

 

Controller erstellen

Der Controller steuert die Datenein- und ausgabe und stellt daher das zentrale Element deiner App dar. Ringhorn beinhaltet keinen dedizierten Router. Das heißt, dass die Controllerklasse und dessen Methoden gleichzeitig die Route abbilden.

Ein Basiscontroller sieht beispielsweise so aus:

# /src/Controller/BaseController.php

namespace App\Controller;

/**
 * @meta route="/base"
 */
class BaseController
{

    /**
     * @meta  route="/index"
     */
    public function index(){
       echo 'Ich bin der Basiscontroller mit der Route "/base", bzw. "/base/index"';
    }
}

Die Route wird aus dem ersten Teil des Klassennamens und der jeweiligen Methode gebildet. Die Methode index wird automatisch aufgerufen, sollte sie in der URL fehlen. Dies gilt jedoch nur dann, wenn keine weiteren URL-Parameter übergeben werden.

Angenommen, der Host lautet example.com, so lauten die verfügbaren Routen für obiges Beispiel:

  1. http://example.com/base oder
  2. http://example.com/base/index

Möchte man erreichen, dass ein bestimmer Controller standardmäßig aufgerufen wird, kann man dies in der Datei .env festlegen.

Ein Controller muss immer als Standard festgelegt werden. Andernfalls wird ein Fehler beim Aufrufen von http://example.com erzeugt.

# .env
DB_TYPE=mysql
DB_HOST=localhost
DB_NAME=test
DB_USER=root
DB_PASS=

APP_SECRET=baldur_
APP_ENV=development

DEFAULT_CONTROLLER=App\Controller\BaseController

 

URL-Query an Controller übergeben

Das Routing sieht im Allgemeinen so aus:

http://example.com/[controller]/[method]/[var]/[var]/[var] usw.

Um die Variablen in der Controllermethode verfügbar zu machen, müssen sie zunächst dort übergeben werden. Nehmen wir folgende URL an:

http://example.com/base/index/hello-world

Wir haben also eine GET-Variable übergeben, nämlich hello-world. Diese machen wir nun in der Methode index verfügbar:

# /src/Controller/BaseController.php
namespace App\Controller;

/**
 * @meta route="/base"
 */
class BaseController
{

    /**
     * @meta  route="/index"
     * @param string|null $a
     */
    function index(string $a = null)
    {
        echo "Deine Eingabe war: $a";
    }
}

Die Variable habe ich standardmäßig auf null gestezt, damit kein Fehler erzeugt wird, wenn diese Angabe in der URL fehlt. Was passieren soll, wenn die Angabe fehlt, möchte ich lieber später in der Controllerlogik festlegen.

# /src/Controller/BaseController.php (auszugsweise)
	/**
	 * @meta  route="/index"
	 * @param string|null $a
	 */
    function index(string $a = null){
		if($a){
			echo "Deine Eingabe war: $a";
		}        
    }

Es ist möglich, die ganze HTML-Ausgabe in die Methode zu packen. Das wird jedoch schnell unübersichtlich und beißt sich mit dem angestrebten MVC-Pattern, wonach die App logisch in die drei Teile Model, View und Controller unterteilt wird.

Die abstrakte Controllerklasse von Ringhorn unterstützt dich dabei und vereinfacht die Webentwicklung erheblich.

 

Abstrakte Controllerklasse

Du kannst deinen Controller mit den Eigenschaften der abstrakten Controllerklasse von Ringhorn erweitern und erhälst so praktische Funktionen, die ich im späteren Verlauf erläutern werde. Eine davon ist das View Objekt $this->view. Weitere Informationen findest du auch in der Ringhorn Referenz.

View rendern

Sende zur Ausgabe im Browser deine Daten vom Controller an den View, um dort festzulegen, wie sie angezeigt werden sollen. Nutze dazu die view->create() Methode, wobei als erster Parameter die php-Datei als String, und als zweiter ein optionales Array mit Daten angegeben wird.

# /src/Controller/BaseController.php
namespace App\Controller;

use Btinet\Ringhorn\Controller\AbstractController;

/**
 * @meta route="/base"
 */
class BaseController extends AbstractController
{

	/**
	 * @meta  route="/index"
	 * @param string|null $a
	 */
    function index(string $a = null)
    {		
        $this->view->create('base/index.php', [
                'eingabe' => $a
            ]
        );        
    }
}

Bei Bedarf kannst du die Twig Template Engine für die HTML-Ausgabe verwenden. Deine Templates speicherst du im Verzeichnis /templates. Im folgenden Beispiel liegt das Template im Verzeichnis /templates/base/index.html.twig

# /src/Controller/BaseController.php
namespace App\Controller;

use Btinet\Ringhorn\Controller\AbstractController;

/**
 * @meta route="/base"
 */
class BaseController extends AbstractController
{

	/**
	 * @meta  route="/index"
	 * @param string|null $a
	 */
    function index(string $a = null)
    {		
        $this->view->render('base/index.html.twig', [
                'eingabe' => $a
            ]
        );        
    }
}

Um Daten vom Controller zur View zu übergeben, benutzt du die Methode $this->view->render();. Diese benötigt zwei Parameter, wobei der zweite optional ist.

Parameter 1
relativer Pfad zum Template (string)

Parameter 2 (optional)
Daten, die ausgegeben werden sollen (array)

Da du im obigen Beispiel im Parameter 2 die Variable $a als eingabe definiert hast, kannst du diese im Template verwenden. In diesem Fall ist es ein String, es sind aber auch Arrays oder Objekte möglich.

Wie die Twig Template Engine genau funktioniert, erfährst du hier. Grundlegendes erzähle ich die aber auch im weiteren Verlauf.

Das Template zur Ausgabe sieht simpel aus, ist es auch. Mit der IF-Schleife wird auch gleich geprüft, ob der übergebene Parameter eingabe null ist oder nicht.

# /templates/base/index.html.twig
<html>
    <head>
        <title>Ringhorn Tutorial</title>
    </head>
    <body>
    {% if eingabe %}
        <p>Deine Eingabe war: {{ eingabe }}</p>
        {% else %}
            <p>Es wurde kein Parameter an die Route angehängt.</p>
    {% endif %}
    </body>
</html>
Routen generieren
Route im Template generieren

Es ist möglich, die Links zu bestimmten Routen zu generieren. Dies geschieht über die Funktion {{ route() }}. Erstelle doch einmal zwei Links, eine mit und eine ohne angehängten Parameter:

# /templates/base/index.html.twig
<html>
    <head>
        <title>Ringhorn Tutorial</title>
    </head>
    <body>
        {% if eingabe %}
            <p>Deine Eingabe war: {{ eingabe }}</p>
            {% else %}
                <p>Es wurde kein Parameter an die Route angehängt.</p>
        {% endif %}
        <a href="{{ route('base/index') }}">Seitenaufruf ohne Parameter</a>
        <a href="{{ route('base/index',{'parameter':'hello-world'}) }}">Seitenaufruf mit Parameter</a>
    </body>
</html>

Wie du siehst, wurde im ersten Link eine Route zum Controller "BaseController" und dessen Methode "index" erstellt. Im zweiten Link wurde zusätzlich noch der Parameter "parameter" mit dem Wert "hello-world" als Array angehängt.

Auf diese Weise lassen sich theoretisch unendlich viele Parameter an die Route hängen, die dann in der jeweiligen Controllermethode verarbeitet werden können.

Route im Controller generieren

Du kannst die Routen aber auch im Controller generieren und dann von dort aus an die View- oder Modelschicht weiterleiten. Kommt darauf an, was du im Einzelnen tun möchtest.

namespace App\Controller;

use Btinet\Ringhorn\Controller\AbstractController;

/**
 * @meta route="/base"
 */
class BaseController extends AbstractController
{

    /**
     * @meta  route="/index"
     * @param string|null $a
     */
    public function index(string $a = null){

        $base_index_route = $this->generateRoute('base/index',[
            'parameter1' => 'eins',
            'parameter2' => 'zwei',
            'parameter3' => 'drei'
        ]);

        $this->view->render('base/index.html.twig', [
            'eingabe' => $a,
            'base_index' => $base_index_route
        ]);
    }
}

Im Twig Template kannst du die generierte Url dann wie jede andere Variable ausgeben (Das funktioniert natürlich auch im reinen PHP mit echo).

<a href="{{ base_index }}">Link zur Route</a>

So bleibt das Template übersichtlicher. Allerdings wird auch der Controller unübersichtlicher.

Redirect zur Route

Manchmal ist es erforderlich, einen Redirect zu einer anderen oder auch der selben Route zu starten. Beispielsweise nach dem Speichern von Daten in der Datenbank oder wenn der Nutzer nicht über die erforderlichen Zugriffsrechte verfügt. Nutze hierzu die Methode $this->redirect().  Diese benötigt zwei Parameter. Zuerst der Redirect-Code und anschließend die Route (keine Parameter möglich).

Im Folgenden ein Beispiel für ein Redirect:

# /src/Controller/BaseController.php
namespace App\Controller;

use Btinet\Ringhorn\Controller\AbstractController;

/**
 * @meta route="/base"
 */
class BaseController extends AbstractController
{

    /**
     * @meta  route="/index"
     * @param string|null $a
     */
    public function index(string $a = null){
        if ($a){
            $this->view->render('base/index.html.twig', [
                'eingabe' => $a
            ]);
        } else {
            $this->redirect('302','base/new');
        }        
    }

    /**
     * @meta  route="/new"
     */
    public function new(){        
            $this->view->render('base/new.html.twig');        
    }
}

In der untenstehenden Tabelle findest du die Redirect Codes und deren Bedeutung:

HTTP Status Code HTTP version Typ
301 HTTP/1.0 dauerhaft
302 HTTP/1.0 temporär
303 HTTP/1.1 temporär
307 HTTP/1.1 temporär
308 HTTP/1.1 dauerhaft

 

Im nächsten Abschnitt erfährst du mehr über das Anlegen von Templates.

Kommentare
Noch keine Kommentare vorhanden.