Kategorien
Laravel

#Kapitel 3: Controller & Co

Bevor ich zu dem Teil kommen kann, wo ich die Datenbank dann tatsächlich verwende, muss ich mich erst einmal mit Controllern und Views beschäftigen. In einem Controller wird die Logik der Anwendung untergebracht, also z. B. werden in einem Controller je nach Eingabe des Nutzers Abfragen an die Datenbank gestellt, die erhaltenen Daten werden ggf. weiter aufbereitet und irgendwann an die View übergeben. In der View wird dann das HTML erzeugt.

Natürlich kann man Controller und Views von Hand anlegen, jedoch gibt es einen einfachen Konsolenbefehl, der einem diese Arbeit abnimmt:

php artisan make:controller TestController

Es wurde die wenig späktakulare Datei /app/Http/Controllers/TestController.php angelegt:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TestController extends Controller
{
    //
}

Übrigens: Alle möglichen Befehle des Tools „artisan“ erhält man mit dem „hilfreichen“ Parameter –help. Siehe dazu:

Artisan Help

Aufruf

Irgendwie muss man den Controller aufrufen können… über eine URL… dazu gibt es Routen. Also alla „ich gebe da www.meinetolleurl.de/test ein und dann soll der TestController verwendet werden“. Diese Definitionen befinden sich an der Stelle /routes/web.php. Das ist ein ziemlich wichtiger Teil von Laravel, deswegen ist die Routen-Dokumentation entsprechend lang :-). Schau ich mir später bzw. bei Bedarf an, im Moment genügt es folgenden Code zu ergänzen:

use App\Http\Controllers\TestController;
Route::get('/test', [TestController::class, 'index']);

Und… was passiert… wer weiß es?

Der Controller ist noch ziemlich leer. Wir benötigen eine Methode, die aufgerufen werden kann. Den obigen Controller um folgende Funktion ergänzen und schon kriegen wir eine Ausgabe:

protected function index() {
    echo "test";
}

Ich möchte eine View dazu verwenden. Ausgaben direkt im Controller sind nur in speziellen Fällen empfehlenswert. Artisan bietet dafür keinen Befehl an, also lege ich die Datei /resources/views/test.blade.php mit dem einfachen Inhalt „Hallo Welt“ an und passe gleichzeitig meine index-Funktion an:

protected function index() {
    return view('test');
}

Das reicht auch schon.

Daten holen

Wenn das Projekt größer wird, kann man chic mit Models arbeiten und das machen wir auch: später. Erstmal einfach den QueryBuilder verwenden:

$testResults=DB::table('test')->get();

Beim Ausführen hagelt es eine Fehlermeldung:

Das wunderte mich. Die Migrations sind durchgelaufen. Da ich in der Doku gelesen habe das ein absoluter Pfad notwendig sei (ich wollte den relativen verwenden), habe ich das in der .env angepasst. Ich habe dazu eine eigene Variable APP_BASE_DIR angelegt, da ich mir vorstellen kann, dass ich das mal wieder benötige:

APP_BASE_DIR=C:/wwwroot/laravel_test/test1/example-app
DB_DATABASE="${APP_BASE_DIR}/storage/app/database.sqlite"

Und siehe da, keine Fehlemeldung mehr. Übrigens: Laravel nutzt zum Auslesen der .env die Biblothek phpdotenv: https://github.com/vlucas/phpdotenv

Um zu sehen, ob die Daten zurückgeliefert werden, habe ich vorerst eine einfache foreach-Schleife hinzugefügt:

class TestController extends Controller
{
  protected function index() {
    $testResults=DB::table('test')->get();
    //++ debug ++//
    foreach ($testResults as $testRow) {
      var_dump($testRow);
    }
    die("go to hell");
    //-- debug --//
    return view('test');
  }
}

Was kommt raus…? „go to hell“… Wichtig! Es kann nur was rauskommen, wenn auch was in der Tabelle steht :-). Also noch eine Zeile ergänzen, die bei jedem Aufruf einen Test-Datensatz erzeugt. Da das Commit in die Datenbank zum Skriptende erfolgt, muss man den Aufruf mindestens zweimal machen, damit die ersten Daten angezeigt werden.

namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;

class TestController extends Controller
{
  protected function index() {
    $testResults=DB::table('test')->get();
    //++ debug ++//
    DB::table('test')->insert(['name' => 'My name is '.md5(rand())]);
    foreach ($testResults as $testRow) {
      echo $testRow->name, '<br>';
    }
    die("go to hell");
    //-- debug --//
    return view('test');
  }
}

Noch schnell die Daten an die View übergeben und dort eine schöne Liste draus machen:

Im Controller:

protected function index() {
    return view('test', ['data'=>DB::table('test')->get()]);
}

In der View /resources/views/test.blade.php:

<ul>
<?php foreach($data as $row): ?>
  <li><?php echo $row->name; ?></li>
<?php endforeach; ?>
</ul>

Ich habe bewusst nicht den Blade-Syntax verwendet. PHP kann erstmal jeder lesen… in Blade funktioniert das folgendermaßen:

<ul>
@foreach ($data as $row)
  <li>{{ $row->name }}</li>
@endforeach
</ul>

Im nächsten Kapitel will ich die Datenebene einer höheren Abstraktion zuführen, also Models verwenden.