Vorwort

Diese Anleitung wurde für Schulungszwecke erstellt, weshalb einiges nicht als fertiger Code zur Verfügung steht. Es soll keine Copy-Paste-Übung werden 😅

Sollte etwas unverständlich oder inkorrekt sein, bitte ich um Feedback um es beheben zu können. Nobody is perfect.

Das MVC Prinzip

https://www.datenbanken-verstehen.de/lexikon/model-view-controller-pattern/
Model – View – Controller

Model: kontrolliert DB
Controller: eigentliche Programmierung
View: Die Anzeige

Laravel gehört zu den MVC-Frameworks.

Um mit Laravel lokal am Rechner entwickeln zu können wird das Programm XAMPP benötigt.
Für Mac-User gibt es als Alternative MAMP

Laravel – Die Magic dahinter

Ich werde hier NICHT auf jedes File und jeden Ordner eingehen, sondern nur einen ersten Einblick geben.

|-- app/
 | |-- Console/
 | |-- Exceptions/
 | |-- Http/
 | |-- Providers/
 | |-- Users.php
 |-- bootstrap/
 |-- config/
 |-- database/
 | |-- migrations/
 | |-- seeds/
 |-- public/
 |-- resources/
 | |-- views/
 |-- routes/
 | |-- web.php
 |-- storage/
 | |-- app/
 | |-- debugbar/
 | |-- framework/
 | |-- |-- cache/
 | |-- |-- sessions/
 | |-- |-- views/
 | |-- logs/
 |-- vendor/
 .env.example
 .composer.json

Der Ordner app

|– Exception: Hier können Ausnahmen definiert werden, was das Programm macht, wenn ein Fehler auftritt.

|– Http: In diesem Ordner verstecken sich der Ordner für die Controller und die Middleware.
Nach dem MVC-Prinzip benötigen wir den Controller für die eigentliche Programmiermagic. Dort werden wir jede Menge Funktionen, Schleifen, Verzweigungen und Abfragen schreiben.
Mit der Middleware können HTTP Requests gefiltert werden. Beispielsweise für verschiedene Sprachversionen, die sich an den Aufenthaltsort des Users anpassen.

|– Providers: Hier sind die Service Provider drin. Sie sind das Rückrad des Laravel-Frameworks.
Eine gute Erklärung zu den Service Providern liefert envatotuts+:
https://code.tutsplus.com/de/tutorials/how-to-register-use-laravel-service-providers–cms-28966

|– Dateien – die Models: Nach dem MVC-Prinzip verwalten wir hier sozusagen die Datenbanktabellen. Für jede Tabelle in der Datenbank (ausgenommen sind meist die Kreuztabellen) gibt es ein Model dazu in diesem app-Verzeichnis. Eine, wie ich finde, gute technische Erklärung zu Models liefert RIP Tutorial: https://riptutorial.com/de/laravel/example/4292/ein-modell-erstellen

Der Ordner config

In diesem Verzeichnis finden sich etliche Konfigurationsdateien. Sie definieren unter anderem wie Laravel die Anweisungen im .env File interpretieren muss, wo Files abgespeichert werden und vieles mehr. Je tiefer du in Laravel eintauchst, desto öfter wirst du hier Anpassungen vornehmen.

Der Ordner database

|– migrations: Die Migrationen bilden deine Datenbank ab. Bei korrekter Handhabung erstellt sich die Datenbank fast wie von allein.

|– seeds: Mit den Seeds können in die Datenbank Daten eingefügt werden. Sehr praktisch, wenn an verschiedenen Geräten gearbeitet wird und die Test Daten nicht immer händisch eingetragen werden wollen.

Der Ordner public

Im Verzeichnis public finden sich Dateien wie das Favicon oder die htaccess-Datei. Dies wird besonders Interessant, wenn das Programm online gehen soll. Prinzipiell werden hier alle Dateien abgespeichert, die gebraucht werden, die öffentlich zugänglich sein dürfen. Dateien mit Passwortzugängen sollten hier demnach nicht abgespeichert werden.

Der Ordner resources

|– views: Hier ist das dritte Prinzip von MVC-Frameworks zu finden. Die Views. Laravel arbeitet bei den Views mit der Blade-Engine. Das bedeutet, eine eigene Syntax statt dirty PHP mit HTML gemischt. Dadurch wirkt der Code nicht nur übersichtlicher sondern die eigene Syntax erleichtert auch einiges bei Abhängigkeiten, Abfragen, Schleifen, Verzweigungen und vielem mehr. In den Views wird das Darstellungsgerüst einer Seite gemanagt.

Der Ordner routes

|– web.php: Jeder Get- oder Post-Request wird in diesem File angeführt. Hier wird die Verbindung zwischen Views und Controller definiert.

Der Ordner storage

|– framework
|   |– cache
|   |– session
|   |– views

Sobald eine View im Browser aufgerufen wird, wird eine html-Seite „gerendert“. Diese wird im Ordner views zwischengespeichert. Ähnlich verhält es sich mit den Sessions und dem Cache.

|– logs: Es wird anfangs oft vorkommen, dass ein Fehler „geschmissen“ wird. Diese werden in den log-Files abgespeichert, die hier ihren Platz finden.

Der Ordner vendor

Das Vendor Verzeichnis beinhaltet alle Laravel Packages. Die Funktionalität von Laravel lässt sich durch eine vielzahl an Packages in viele Richtungen erweitern.

Das File composer.json

In dieser Datei werden die Meta Daten der Packages festgehalten und was der Autoloader machen soll.

Windows PowerShell / Eingabeaufforderung

Ich persönlich bevorzuge die Windows PowerShell. Ist aber reine Geschmackssache.

$ cd C:\xampp\htdocs

Wechseln zu dem Ordner htdocs

$ composer -v

Überprüfen ob Composer installiert ist. Wenn nicht: INSTALLIEREN und Computer neu starten

$ composer global require laravel/installer

Laravel Installer installieren

$ laravel new lexikon-advanced

erstellt einen Ordner mit einer Laravelinstallation namens lexikon-advanced

$ cd lexikon-advanced

In Laravel Installation navigieren

$ composer require barryvdh/laravel-debugbar --dev

Sehr nützliches Plugin auf das ich später noch zu sprechen komme.

$ php artisan serve

Startet den Server damit wir uns im Browser die Seiten ansehen können.

Server stoppen Mac/Windoof (Strg + c) – Fehlt noch

Datenbank

Für das Lexikon benötigen wir natürlich eine Datenbank.
Ich beginne meist mit einem Stift und einen Blatt Papier um mir meine Ideen zu Visualisieren. Danach wechsle ich meist, vorallem bei umfangreichere Projekte, auf die MySQL Workbench.
Hier liebe ich es mit den Models und den EER Diagrammen zu „spielen“.

Im ersten Anlauf wird unser Lexikon ganz einfach und besitzt auch keinerlei Fremdschlüssel. Allerdings werden wir die vorgefertigten Files für die Authentifizierung anpassen.

Die Authentifizierung

Ich liebe Laravel.. Es gibt für so vieles schon etwas vorgefertigtes ❣️
Beispiel: Authentifizierung. Mit zwei einfachen Befehlen in der PowerShell wird die ganze Logik, dh Controller, Route, Views, Model, usw. erstellt.

„Laravel’s laravel/ui package provides a quick way to scaffold all of the routes and views you need for authentication using a few simple commands:

$ composer require laravel/ui
$ php artisan ui vue --auth

Datenbank Migrationen

Eine Migration müssen wir dennoch schreiben und die zweite anpassen.

Die Migrationen finden sich im Ordner „database > migrations“

Auf der offiziellen Laravelseite kannst du nachschauen, wie du die Migration schreiben musst: https://laravel.com/docs/6.x/migrations#columns
Achte auf die Versionsnummer rechts oben! Sie sollte mit der Version, die du installiert hast zusammen passen!

$ php artisan make:migration create_tablename_table

Nachdem Laravel seine Migrationen mit „create_“ anfängt und hinten „_table“ dran hängt, benenne ich meine Migrationen dementsprechend auch so. Die Random Nummer mit dem Datum vergibt Laravel von allein. Dadurch wird die Reihenfolge in der die Migrationen abgearbeitet werden, festgelegt. Das wird vorallem dann wichtig, wenn Fremdschlüssel zum Einsatz kommen und hat mich in meiner Anfangszeit schon viele Stunden gekostet 😅

… wenn die Content Migration fertig geschrieben ist und die bestehende create_users_table nach der Vorlage des Workbench Screenshots abgeändert wurde,gibt es noch zwei Dinge, die wir machen müssen, bevor wir unser Glück mit den Migrationen versuchen können.

1. Wir öffnen das Programm „XAMPP“ und starten den Apache und den MySQL Server. Wir brauchen eine Datenbank im phpMyAdmin. (Wenn du zu dem Thema phpMyAdmin von mir eine Anleitung lesen möchtest, dann gib Bescheid).

2. Wir müssen unserer Laravel Installation irgendwo sagen, wo die Datenbank ist und wie sie sich verbinden kann. Das können wir im „.env“ File machen, dass im Wurzelverzeichnis unserer Installation liegt. Nach der Installation heißt es noch „.env.example“. Das gehört geändert in nur „.env“. Sollten die Dateien nicht angezeigt werden, müsst ihr dies in Windows erst erlauben: https://support.microsoft.com/de-at/help/14201/windows-show-hidden-files
Sollten die Dateiendungen nicht ersichtlich sein, wäre das auch eine gute Gelegenheit sie einzublenden….

Im .env File sind für uns vorerst nur die Zeilen mit DB_ interessant.
Die lokale phpMyAdmin Installation hat meist kein Passwort gesetzt und der Benutzername ist default „root„. Bei DB_DATABASE tragt ihr wie unten zu sehen den Namen der Datenbank die wir in Step eins vor wenigen Minuten erstellt haben. Und ja, da fehlen Leerzeichen und das soll so sein.

DB_CONNECTION=mysql
 DB_HOST=127.0.0.1
 DB_PORT=3306
 DB_DATABASE=datenbankname
 DB_USERNAME=root
 DB_PASSWORD=

.jetzt können wir unser Glück in der PowerShell versuchen…

$ php artisan migrate

… Bugfixen …. Die PowerShell sagt dir normalerweise in welcher Zeile der Fehler liegt, bzw. welche Zeile in den Migrationen nicht verarbeitet werden konnte. Also genau lesen 😉
Sollte der Fehler „Specified key was too long“ kommen, findet ihr hier eine Beschreibung, wie der zu fixen geht: https://laravel-news.com/laravel-5-4-key-too-long-error
Auch wenn sich dieser Fehler auf die Laravel Version 5.4 bezieht, ließ sich das Problem bei mir bisher auch in neueren Versionen so lösen.

$ composer dumpautoload

Leert den Cache. Sehr nützlich, vorallem wenn man händisch die Reihenfolge oder den Namen von Migrationen ändert

Controller und View anpassen

Wir haben unsere Tabelle Users etwas anders gestalten, als Laravel es vorgegeben hat. Diese Änderung muss an drei Stellen angepasst werden.

Der RegisterController.php

unter app\Http\Controllers\Auth\RegisterController.php findet man den Registierungscontroller. Hier ist ab ca Zeile 50 die Logik definiert, das der User beim Ausfüllen des Registrierungsformulars in der Datenbank abgespeichert wird. Da wir die Users-Tabelle leicht modifiziert haben, müssen die Änderungen hier ebenfalls übernommen werden.

Das User.php Model

Unter app\User.php ist das Model abgespeichert. Hier sehen wir mit der Zeile protected $table = "users", dass dieses Model die Tabelle users managt. Die Zeile protected $fillable = [ .... ] muss ebenfalls angepasst werden, da die Daten sonst nicht in der Datenbank abgespeichert werden.

Die View register.blade.php

Unter resources\views\auth\register.blade.php wurde die View für die Registrierung angelegt. Diese muss natürlich auch angepasst werden, an die neue Tabellenstruktur.

Die Blade-Syntax in der register.blade.php

@extends('layouts.app')
Mit dieser Zeile verbinden wir die Registrierungsseite mit dem Layout. Der Vorteil ist, dass alle Elemente, die wir auf jeder oder vielen Seiten brauchen (Tags in der Grundstruktur, CSS Dateien, JS Dateien) sind im app.blade.php definiert, dass im Verzeichnis resources\views\layouts zu finden ist.

@sections('content')
    // ganze Seiteninhalt 
 @endsection

Die section-Anweisung mit dem Namen content signalisiert dem app.blade.php, dass alles was innerhalb dieser Anweisung steht, in unser Grundgerüst integriert werden soll.

Daten auslesen

Damit wir sehen ob es funktioniert, muss jetzt der Server gestartet werden mit $ php artisan serve

Unter http://127.0.0.1:8000/ sollte nun die Welcome Seite von Laravel sichtbar sein, inklusive einem Login und Registry Button im rechten oberen Eck. Die Registrierung werden wir jetzt ausprobieren.

Damit wir sehen ob der Rest auch funktionieren brauchen wir ein paar Dummy Daten in der Datenbank. Hierfür in der Datenbank direkt einfach in der content-Tabel 2-3 Einträge eintragen.

erste Seite mit den Daten aus der Datenbank

die View

Im Ordner resources\views erstellen wir ein file: lexikon.blade.php
In unserem lexikon-Blade binden wir als erstes das Layout ein mit:

@extends('layouts.app')
@section('content')
  <!-- -|- hier kommt dann der Rest -|-->
@endsection

Um das File aufrufen zu können brauchen wir eine Route um die URL im Browser mit dem File und mit dem Controller zu verbinden
Im File: routes\web.php definieren wir die Route mit:
Route::get('/lexikon', 'PageController@lexikon')->name('lexikon');

Banal ausgedeutscht steht da nichts anderes wie: Von der Adresse „lexikon“ bekomm ich eine Anfrage die im PageController unter der Funktion „lexikon“ verarbeitet werden soll und der Name von der ganzen Aktion ist „lexikon“.
Diese Route Names müssen einzigartig sein! Der Vorteil von Route Names sind, dass wenn ich in einem Controller auf eine Route verweisen will, ich diesen Namen benutzen kann. Wir werden im späteren Verlauf sehen, dass der Route Name um einiges Kürzer ist, als die „Adresse“.

Zusammengefasst: Diese Route verweist jetzt von der URL http://127.0.0.1:8000/lexikon auf den Controller PageController und dort drin auf die Funktion lexikon.

Damit das auch funktioniert erstellen wir den PageController mit folgendem Befehl in der Eingabeaufforderung/PowerShell

$ php artisan make:controller PageController
Nun haben wir in  app\Http\Controllers das File PageController.php

Der PageController.php

Damit wir auf das Model Zugriff haben, müssen wir diese erst registrieren. Durch use App\Content; können wir innerhalb der Funktion lexikon() mit Content::get(); auf den Inhalt der Tabelle content in der Datenbank zugreifen.
Das heißt: Durch use App\Content; haben wir Zugriff auf das Model app/Content.php. Dadurch holt sich Laravel mit Content::get(); alle Einträge in der Tabelle content.

Layout – app.blade.php

Im File app.blade.php generiert Laravel das Grundgerüst der HTML Seite.
Im <html>-Tag wird die Sprache durch die Systemeinstellung des Computers des Users automatisch gesetzt.
Den Title setzt er default auf Laravel wenn im .env File nichts gesetzt wurde.

Als erstes ersetze ich die Bootstrap Verlinkungen durch die neuere Version von der offiziellen Bootstrap Seite im <head> Bereich und am Ende der Seite (Achtung, jQuery wird dieses Mal im <head> definiert, nicht am Ende der Seite): https://getbootstrap.com/docs/4.4/getting-started/introduction/

Im Verzeichnis resources\js lösche ich das bootstrap.js (wird ja über cdn geladen).

Die Navigation ist prinzipiell eine Standard-Bootstrap-Navbar. Typisch für die Laravel Syntax sind die {{  }} geschwungenen Klammern. Sie ersetzen die in PHP notwendige Zeichenkombination <?php   ?>

asset gehört zu den sehr praktischen und hilfreichen 😁 Helfermethoden in Laravel:
https://laravel.com/docs/master/helpers#method-asset

Interessant ist nach der Navigation was im <main>-Tag steht.
@yield('content')
Hier wird der Inhalt der View eingefügt der in zum Beispiel in der registry.blade.php innerhalb der @section('content') steht.

Innerhalb der View lexikon.blade.php schauen wir uns mal an welche Daten wir bekommen haben

{{ dd($content) }}

dd() ist eine sehr hilfreiche Methode in Laravel. Es ist ein erweitertes Äquivalent zu var_dump() (nur besser 😉 )

Wenn irgendwo dd() ausgegeben wird, wird der restliche Inhalt nicht mehr geladen!

Ajax und Bootstrap Modal

Daten aus der Datenbank darstellen

Damit ihr Ajax benutzen könnt müsst ihr entweder das normale jQuery (nicht die SLIM-Version wie es Bootstrap gewöhnlich verwendet) im head Bereich einbinden, oder das Script für das absenden global im app.blade.php schreiben. Ich tendiere hier eher dazu, jQuery im head Bereich einzubinden, da das Script sonst auf jeder Seite geladen wird obwohl ich es nur in einem File brauche…
In welcher Reihenfolge ihr untenstehende Punkte macht ist relativ egal

routes/web.php

Im web.php leg ich eine neue Route an
Route::post('/dataToModal', 'AjaxController@dataToModal');

resources/welcome.blade.php

in diesem File habe ich innerhalb einen Button definiert mit der Klasse showModal und einer eindeutigen ID => ID aus der Datenbank des jeweiligen Eintrags.
Am Ende des Files gibt es noch einen leeren div-Container mit einer id.
Im Script selbst definiere ich erst einmal ein ajaxSetup für den CSRF-Token.
Auf die Klasse des Buttons setze ich ein click-Event (showModal). In der Funktion speichere ich mir die ID des Button in die Variable content_id. Die brauch ich später, um in der Datenbank den Eintrag zu finden.
Im Ajax Teil definiere ich die URL über die der POST gehen soll und gib die content_id mit, die im Controller im Request ankommt.
Wenn das ganze erfolgreich war, bekomm ich dann das File zurück, das ich in Punkt 3 erstelle, mit den Daten aus der Datenbank, die ich in Punkt 5 mir hole. Das Packet schmeiß ich in mein leeres Div mit der id modalContainer und (dank jQuery und Bootstrap) kann ich durch die ID vom Modal (Achtung: nicht die vom div-Container!!) einfach sagen „show me“!

resources/modal/contentModal.blade.php

ist ein neues File das erstellt wurde. Hier drin ist ein ganz normales Bootstrap Modal inklusive der Variablen {{$entry->title}} und {{$entry->description}}. Ich sollte mir hier an dieser Stelle für den Controller merken, dass die Variable $entry heißt.

resources/layouts/app.blade.php

Im app.blade.php habe ich lediglich das jQuery ausgetauscht zu der unkomprimierten Version und habe die im head-Bereich eingebunden.

app/Controller/AjaxController.php

Ich erstell einen neuen Controller für meine Ajax-Abfragen. Hier definiere ich wieder mal, dass das Model use App\Content; eingebunden wird, damit ich auf die Content Tabelle zugreifen kann.
Im eigentlichen Controller Segment erstelle ich eine Funktion namens dataToModal und sag der Funktion durch Request $request das er einen Request bekommt und den in der Variable $request speichern soll. Innerhalb der Funktion hol ich mir den Eintrag aus der Datenbank, wo die id gleich der $request->content_id ist. Mit first() sorge ich dafür das es eine Collection und kein Array ist. Sicherheitshalber schau ich dann mal ob der Eintrag eh in die Variable $entry gespeichert wurde. Wenn ja dann gib mir die View, die in resource/modal/contentModal.php ist zurück mit der Variable $entry.