Immer öfter bekomme ich die Frage gestellt, wie Daten mit Laravel verwaltet werden können. Damit ist das klassische CRUD gemeint. (C)reate, (R)ead, (U)pdate und (D)elete. Oder ganz einfach: Daten erstellen, Daten anzeigen, Daten aktualisieren und Daten löschen. Das kann man mit einem Laravel Resource Controller wirklich super einfach machen. Ich zeige dir das hier anhand der Admin eines Mini Online Shops. Es gibt User und Produkte. Es wird keine grafischen Spielereien geben. Es geht alleine um die Daten. Nach dem Tutorial solltest du in der Lage sein deine Daten in Laravel zu verwalten.
In diesem Tutorial gehe ich davon aus, dass du bereits ein neues Laravel Projekt initialisiert hast. Falls du noch nie mit Laravel gearbeitet hast, dann schau dir mein Laravel Anfänger Tutorial an. Danach kannst du dann hier weiter machen. Auch die Datenbank sollte schon korrekt konfiguriert sein.
Das Tutorial basiert auf Laravel V5.4.26
Was lernst du hier
Neben dem Resource Controller Konzept von Laravel werde ich dir hier auch noch die Laravel Model Factories zeigen. Und du wirst sie lieben. Es vereinfacht die Entwicklung so ungemein. Doch dazu später mehr.
Die Url zu meinem lokalen Projekt heißt: http://minishop.dev/
Was wir brauchen
- User Model (existiert bereits nach der Installation)
- Produkt Model
- Produkt Model Factory
- Produkt Resource Controller
- Routen
- Diverse Views
Laravel Resource Controller erstellen
Ich initialisiere meine Projekte immer mit dem Standart Laravel Benutzersystem.
php artisan make:auth
Das Schöne daran ist, dass ich jetzt bereits eine fertige Benutzer Registrierung und eine Login Möglichkeit habe.
Produkte Model, Controller und Migration
php artisan make:model Product -mrc
Damit wird das Model unter /app/Product.php, der Resource Controller unter /app/Http/Controllers/ProductController.php und die Datenbank Migration unter /database/migrations/XXX_XX_XX_XXXXXX_create_products_table.php angelegt. Der Resource Controller enthält schon die leeren Methoden, die wir gleich benötigen. Views werden aber noch nicht generiert.
Als nächstes bearbeite ich die Migration für das Produkt Model in /database/migrations/XXX_XX_XX_XXXXXX_create_products_table.php.
Die up() Methode sieht dann so aus
public function up() {
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->string('name');
$table->text('description');
$table->integer('price');
$table->timestamps();
});
}
$table->unsignedInteger('user_id');
enthält die User Id des Erstellers. unsignedInteger bedeutet, dass es sich hier um einen positiven Integer Wert handelt. Die drei anderen hinzugefügten Zeilen sind der Name (name), die Beschreibung (description) und der Preis (price) des Produktes. Den Preis speichere ich grundsätzlich als Cent Preis.
Die Migration führen wir auf der Konsole aus
php artisan migrate
Product Model Factory
Model Factories in Laravel vereinfachen die Entwicklung enorm. In /database/factories/ModelFactory.php werden sogenannte Model Factories definiert. Das spannende daran ist, dass wir später damit Datenbankeinträge erzeugen können auf Grundlage von Faker. Also gefakete Daten. Das hat den Vorteil, dass wir so schnell Demo oder auch Test Daten erzeugen können.
Die Factory für unser Produkt sieht so aus
$factory->define(App\Product::class, function (Faker\Generator $faker) {
return [
'user_id' => factory('App\User')->create()->id,
'name' => $faker->word(),
'description' => $faker->paragraph(),
'price' => $faker->randomNumber(4)
];
});
'user_id' => factory('App\User')->create()->id
erzeugt aus der bereits existierenden User Factory einen neuen Benutzer und gibt die ID zurück.'name' => $faker->word()
erzeugt einen String, der hier den Produktnamen darstellen soll.'description' => $faker->paragraph()
erzeugt einen Text, der die Produktbeschreibung enthält.'price' => $faker->randomNumber(4)
erzeugt eine vierstellige Zufallszahl, die wir hier als Preis benutzen.
Um das mal zu testen, starte einfach auf der Konsole
php artisan tinker
Das ist ein Kommandozeilen Tool für Laravel.
Hier testen wir jetzt die Produkt Factory mit
factory('App\Product', 10)->create();
Es erscheinen jetzt die 10 Einträge, die automatisch erzeugt wurden. Dafür sorgt das ->create()
. 'App\Product', 10
sagt welches Model genutzt werden soll und wieviele Daten erzeugt werden.
App\User::all();
zeigt dir alle Benutzer an. Durch unsere Factory wurden hier auch 10 neue Benutzer erzeugt.
Eintrag Übersicht
Jetzt, da wir ein paar Produkte bereits in der Datenbank haben, können wir die auch mal anzeigen lassen.
In /routes/web.php füge ich eine neue Resource Route ein
Route::resource('admin/product', 'ProductController');
Damit weiß Laravel, dass alles was mit /admin/route anfängt zum ProductController gehört.
In /app/Http/Controllers/ProductController.php fülle ich die index() Methode mit
public function index() {
$products = Product::all();
return view('admin.product.index', compact('products'));
}
Hier werden alle Produkte geholt und an die View admin.product.index übergeben.
Die View erzeugen wir in /resources/views/admin/product/index.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Produkte</div>
<div class="panel-body">
@foreach($products as $product)
<h4>{{ $product->name }}</h4>
<p>{{ $product->description }}</p>
<p><strong>{{ number_format(($product->price/100), 2) }}€</strong></p>
<hr>
@endforeach
</div>
</div>
</div>
</div>
</div>
@endsection
Du kannst jetzt schon http://minishop.dev/admin/product die Seite aufrufen und solltest Produkte sehen. Ganz schlicht gehalten, aber du erkennst schon wie einfach das ist.
Neuen Eintrag anlegen (C)reate
Wie das Erstellen neuer Einträge über die Model Factory funktioniert, hast du gesehen. Wie du über ein Formular neue Produkte erzeugen kannst, siehst du im nächsten Schritt. Hier ziehe ich das Tempo etwas an. Wenn du Fragen dazu hast, dann hinterlass einfach einen Kommentar.
/app/Http/Controllers/ProductController.php Methode create()
public function create() {
return view('admin.product.create');
}
View /resources/views/admin/product/create.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Neues Produkt erstellen</div>
<div class="panel-body">
@if($errors->any())
<div class="alert alert-danger" role="alert">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="/admin/product" method="post">{{ csrf_field() }}
<div class="form-group">
<label for="name">Name</label>
<input id="name" class="form-control" name="name" required="" type="text" value="{{ old('name') }}" placeholder="Produkt Name">
</div>
<div class="form-group">
<label for="description">Beschreibung</label>
<textarea id="description" class="form-control" name="description" required="" rows="3">{{ old('description') }}</textarea>
</div>
<div class="form-group">
<label for="price">Preis (in Cent)</label>
<input id="price" class="form-control" name="price" required="" type="text" value="{{ old('price') }}" placeholder="Produkt Preis in Cent">
</div>
<button class="btn btn-primary" type="submit">Produkt anlegen</button>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Alles von @if($errors->any())
bis zum @endif
wird für die Fehleranzeige benötigt. Das kann man auch ganz gut auslagern und dann später in jeder View anzeigen lassen die Fehlermeldungen ausgibt. Oder man packt es ins Layout. Damit es einfacher ist, lasse ich es hier in der View. {{ old('name') }}
sorgt dafür, dass bei einer fehlerhaften Validierung hier die eingegebenen Daten wieder zu sehen sind. Gerade bei längeren Formularen nervt es, wenn man alles wieder neu eingeben muss.
Danach wird dann das Formular erzeugt. Hier füge ich gerne das HTML5 Tag required hinzu, wenn eine Eingabe erforderlich ist. Hier sollte man sich aber nicht darauf verlassen. Eine serverseitige Validierung der Daten ist auf jeden Fall notwendig.
Jetzt muss das Ganze natürlich noch in der Datenbank gespeichert werden. Das geschieht in der store() Methode in /app/Http/Controllers/ProductController.php
public function store(Request $request) {
$this->validate($request, [
'name' => 'required',
'description' => 'required',
'price' => 'required|integer'
]);
$product = new Product();
$product->user_id = auth()->id();
$product->name = request('name');
$product->description = request('description');
$product->price = request('price');
$product->save();
return redirect('/admin/product');
}
Als erstes werden hier die Eingaben validiert. Ganz stumpf einfach ob der Name (name), die Beschreibung (description) und der Preis (price) eingegeben wurde und ob der Preis eine Integer Zahl ist. Ist das nicht der Fall, macht Laravel automatisch einen Redirect auf das Formular und führt den Code unter der Validierung gar nicht erst aus. Auch die Fehlermeldungen werden automatisch übergeben und dann in der View wieder ausgegeben. Sehr nice.
Falls die Validierung durchläuft, also die Daten korrekt sind, erzeugen wir ein neues Product Objekt. Das befüllen wir hier mit den Request Daten mit der Laravel Helfer Funktion request()
. $product->user_id = auth()->id();
hier holen wir die ID von dem eingeloggten Benutzer. Mit $product->save();
speichern wir die Daten in die Datenbank. return redirect('/admin/product');
führt zurück auf die Produkt Übersicht.
Damit man gar nicht erst Produkte erstellen kann ohne eingeloggt zu sein, fügen wir in /app/Http/Controllers/ProductController.php noch im Konstruktor die Auth Middleware ein.
public function __construct() {
$this->middleware('auth');
}
Von nun an, sind alle Routen die auf den ProductController enden geschützt und verlangen einen Login. In diesem Beispiel ist das aber nur ein ganz einfacher Schutz. Hier wird nur der Login (Authentication) und nicht die Zugriffsberechtigung (Authorisation) geprüft. Aber für jetzt reicht uns das erstmal.
Dann kannst du jetzt mal auf http://minishop.dev/admin/product/create gehen ein neues Produkt anlegen.
Hat es geklappt? Prima!
Eintrag anzeigen (R)ead
Als nächstes zeigen wir ein Produkt im Detail an. In einem Resource Controller übernimmt das die show() Methode.
/app/Http/Controllers/ProductController.php
public function show(Product $product) {
return view('admin.product.show', compact('product'));
}
Hier ist schon ein bisschen „Magic“ drin. Mit show(Product $product)
wird hier schon das richtige Produkt Objekt für uns geholt. Da müssen wir uns gar nicht drum kümmern. Wenn man sich an gewisse Konventionen von Laravel hält, kann man das die ganze Anwendung hindurch so einfach nutzen. Das Produkt Objekt übergeben wir dann an die View.
/resources/views/admin/product/show.blade.php
@extends('layouts.app') @section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">{{ $product->name }} {{ $product->price }}</div>
<div class="panel-body">
<p>{{ $product->description }}</p>
</div>
</div>
</div>
</div>
</div>
@endsection
Das Aufruf eines einzelnen Produktes erfolgt über http://minishop.dev/admin/product/1
Also (C)reate haben wir, (R)ead auch. Fehlt noch (U)pdate und (D)delete. Auch das ist keine Zauberei.
Eintrag aktualisieren (U)pdate
Das Formular um ein Produkt zu ändern sieht ähnlich aus wie das Formular um ein Produkt zu erstellen. Du kannst später noch die Teile auslagern, die gleich sind.
/app/Http/Controllers/ProductController.php edit() Methode
public function edit(Product $product) {
return view('admin.product.edit', compact('product'));
}
Auch hier ist wieder die „Magic“ drin und wir übergeben das Produkt Objekt an die View.
/resources/views/admin/product/edit.blade.php
@extends('layouts.app') @section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">{{ $product->name }} bearbeiten</div>
<div class="panel-body">@if($errors->any())
<div class="alert alert-danger" role="alert">
<ul>@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach</ul>
</div>
@endif<form action="/admin/product/{{ $product->id }}" method="post">{{ csrf_field() }} {{ method_field('PUT') }}
<div class="form-group"><label for="name">Name</label> <input id="name" class="form-control" name="name" required="" type="text" value="{{ $product->name }}" placeholder="Produkt Name"></div>
<div class="form-group"><label for="description">Beschreibung</label> <textarea id="description" class="form-control" name="description" required="" rows="3">{{ $product->description }}</textarea></div>
<div class="form-group"><label for="price">Preis (in Cent)</label> <input id="price" class="form-control" name="price" required="" type="text" value="{{ $product->price }}" placeholder="Produkt Preis in Cent"></div>
<button class="btn btn-primary" type="submit">Produkt aktualisieren</button></form></div>
</div>
</div>
</div>
</div>
@endsection
.Das ist die Route für das Update. Im CRUD ist das Update eigentlich ein PUT. Nur funktioniert das in HTML nicht. Daher wird das von Laravel mit {{ method_field('PUT') }}
simuliert. Die Formularfelder werden mit value="{{ $product->name }}"
vorbelegt.
Das aktualisieren erfolgt in der update() Methode.
/app/Http/Controllers/ProductController.php
public function update(Request $request, Product $product) {
$this->validate($request, [
'name' => 'required',
'description' => 'required',
'price' => 'required|integer'
]);
$product->name = request('name');
$product->description = request('description');
$product->price = request('price');
$product->save();
return redirect('/admin/product');
}
Das ist jetzt ähnlich der store() Methode weiter oben. Auch hier erfolgt die Validierung. Das könnte man sicher noch auslagern um keinen doppelten Code zu erzeugen. Danach wird das bereits injizierte Produkt Objekt mit den neuen Daten befüllt und gespeichert. Die user_id wird hier nicht neu vergeben, da sich der Ersteller des Produkts ja nicht geändert hat. Danach folgt wieder der Redirekt auf die Produkt Übersicht.
Du kannst das ganz einfach unter http://minishop.dev/admin/product/1/edit testen.
Eintrag löschen (D)elete
Das löschen eines Eintrags mit Laravel ist etwas komplizierter, als es sich anhört. Laravel hält sich hier strikt an die RESTful Methodik. Das ist aber nicht weiter schlimm, solange man das weiß.
Wir passen daher jetzt unsere Produkt Übersichts Seite etwas an.
Auszug aus /resources/views/admin/product/index.blade.php
...
@foreach($products as $product)
{{ $product->name }}
{{ $product->description }}
{{ number_format(($product->price/100), 2) }}€
{{ method_field('DELETE') }}
{{ csrf_field() }} Produkt löschen
@endforeach
...
Neu ist hier, dass für jeden einzelnen Eintrag ein Mini Formular mit einem Button erzeugt wird. Außerdem wird ein Hidden Field mit einer Pseudo Methode DELETE eingefügt.
Entsprechend einfach ist die Methode destroy() in /app/Http/Controllers/ProductController.php
public function destroy(Product $product) {
$product->delete();
return back();
}
Ist das nicht einfach?
Fazit
Damit sind wir am Ende des Laravel CRUD Tutorials. Du hast gelernt wie einfach es ist mit Laravel Daten in die Datenbank zu bekommen. Sicherlich gibt es einige Verbesserungsmöglichkeiten. Aber genau hier kommst du dann ist Spiel. Du wirst deine eigenen Erfahrungen machen und auch auf Probleme und Fragen stossen. Daher wäre es super, wenn du hier einen Kommentar hinterlassen würdest. Ich freue mich darauf.
Und falls du immer noch nicht genug von Laravel hast, dann hol dir doch einfach mein kostenloses Laravel Anfänger Tutorial E-Book.
Klasse Tutorial! Hat mir den Einstieg wirklich erleichtert.
Bin aber auf nen kleines Problem gestoßen oder man könnte auch sagen, dass hier ein kleiner Zusatz noch super praktisch wäre.
Eine kurze Erklärung wie oder wo man eine Datenbank einbinden kann, wäre sicher hilfreich. Sollte man das nämlich nicht getan haben, kann es passieren, dass ‚factory(‚App\Product‘, 10)->create();‘ folgenden Fehler auswirft:
‚PHP Fatal error: Allowed memory size of 2097152 bytes exhausted (tried to allocate 4096 bytes) in C:\…\Illuminate\Container\Container.php‘
Der kleine Trick memory_limit = -1 in der php.ini behebt diesen. Beide Arten, sowohl DB als auch der Trick, sind also möglich und valide. Aber Anfänger und alle die zu faul zum suchen sind stolpern vielleicht über den Fehler und geben auf.
Vielleicht gibt es dazu auch schon ein Tutorial oder eine Erwähnung, und ich habe es nur überlesen und nicht gefunden. So oder so, vielen Dank für das Tutorial und mach weiter so!
Viele Grüße
Hi und vielen Dank für die netten Worte.
Mit memory_limit = -1 musst du aber vorsichtig sein. Meistens hat es einen Grund warum es die Meldung „Allowed memory size of …“ kommt. Ich persönlich fange mit 256M an und gehe auf maximal 512M. Je nach Speicher auf dem Server. Das gilt für das Live System. Lokal kannst du natürlich nehmen was du willst.
Hallo, ich habe soeben Ihr Tutorial durchgeführt. Dabei bin ich bei Create auf das Problem gestoßen, dass die Daten aus der Tabelle in die URL übergeben werden, aber nicht in der Datenbank gespeichert werden. Wissen Sie zufällig, woran das liegen könnte?
Hi,
die Daten sind in der Adresszeile des Browsers zu sehen? Verstehe ich das richtig?
Ist die Zeile
in /resources/views/admin/product/create.blade.php korrekt?
Ansonsten schick mir mal einen Screenshot per E-Mail an info@dirk-helbert.de
Danke für das Tutorial, Grundprinzip verstanden, nur wie baut man sich jetzt die komplizierten Dinge, wie verschiedene Nutzer-Level, von Admin und Backend-user bis Kunde bzw. Gast oder und Backend bis Statistik ?!?!
Das machst du am besten mit dem Zusatzpaket von Spatie.
https://github.com/spatie/laravel-permission
Semantik: In
/resources/views/admin/product/create.blade.php (Zeile 27) und
/resources/views/admin/product/edit.blade.php (Zeile 28)
soll beim Label bestimmt for=“description“ anstatt for=“name“ sein.
Sehr gut aufgepasst 🙂 Das stimmt natürlich und habe ich direkt mal korrigiert. Vielen Dank!
Am Anfang des Tages hatte ich noch kaum Ahnung von Laravel, aber jetzt bin ich schon ein gutes Stück weitergekommen. Danke.
Hallo Marcel,
es freut mich, wenn ich dir ein bisschen weiterhelfen konnte. Du kannst dir auch mein kostenloses E-Book runterladen.
Viele Grüße
Dirk
Bei mir zeigt der leider:
Objekt nicht gefunden an… Kannst du mir sagen woran das liegen kann?
Ich hatte unter /resources/views die Ordner
/admin/product/ nicht und habe die manuell angelegt.
Grüße
Patrick
Hi Patrik,
kannst du mal einen Screenshot von der kompletten Fehlermeldung machen. Kannst du mir auch per Mail schicken an info@dirk-helbert.de
Viele Grüße
Dirk
Hatte nur die URL falsch eingegeben. Leider wird beim „Create“ aber nicht in die Datenbank geschrieben 🙁 Es erscheint lediglich die Übersicht der Datensätze – keine Erfolgsmeldung oder eine Fehlermeldung… Gibt es sowas wie ein Log oder wie man anschauen kann was er falsch macht?
Ja. Ein Log gibt es unter /storage/logs/laravel.log. Da wird ggf. etwas reingeschrieben.
Also nun klappt es 🙂
Ich hab noch eine Frage: Ist es möglich das bspw. der User nur die Einträge sieht die er selber angelegt hat – oder zumindest das man sieht welcher Benutzer welchen eintrag angelegt hat?
Sagen wir Ich lege ein Produkt an und ein anderer Legt auch ein Produkt an. Ich möchte aber sehen wer das Produkt angelegt hat.
Hi Patrick,
dazu müsstest du in der Produkt Tabelle die User Id mit speichern. Beim holen der Daten beschränkst du dann die Ergebnisse auf die mit der jeweiligen User Id.
Viele Grüße
Dirk
Fragen über Fragen – tut mir leid 🙁 aber dieses Tutorial hat mir laravel gezeigt und ich bin so geil drauf 😀
Wie ich jetzt Buttons erstelle mit Edit etc. ist einleuchtend und das habe ich geschafft.
Eine weitere Frage wäre jetzt sowas wie eine „View“. Ich will bspw. das Produkt nur als Ausschnitt sehen – wenn ich aber drauf klicke bekomme ich alle Informationen gezeigt.
LG Patrick
Sorry – hatte das Tut nochmal gelesen. Da wirds erklärt 😀 Man ist Laravel hammer – man bekommt schnell gute Ergebnisse hin die für den ein oder anderen Zweck sehr nützlich sind.
Ja, Laravel ist wirklich sehr sehr gut. Gerade im Bereich PHP das für mich intuitivste Framework. Es ist einfach logisch.
Hallo Dirk,
ich habe jetzt eine ganze Menge gelernt und bin sehr sehr weit gekommen. Jedoch stecke ich gerade fest und auch StackOverflow kann mir nicht wirklich helfen.
Ich erstelle mit deinem CRUD einen Kunden. Jetzt habe ich 3 Buttons:
Edit
View
Delete
Wenn ich in die View gehe dann sehe ich die Details zu dem Kunden. jetzt will ich ein PDF schreiben (soll als angebot dienen mit angebotsnummer) welches sich die Daten zu dem Kunden holt. Dieses PDF soll dann dem Kunden zugeordnet werden und entweder in einem Verzeichnis oder in der Datenbank gespeichert werden.
Leider komme ich keinen Schritt weiter. Wie ich Daten aus der Datenbank für ALLE Kunden bekomme habe ich geschafft. Leider aber nicht für einen Kunden speziell… Ich hoffe du kannst mir helfen
Hi Patrick,
sind Kunden bei dir in der User Tabelle oder einer Customer Tabelle?
Ich gehe mal von Customer Tabelle aus, aber das Prinzip ist ja das gleiche.
Alle Kunden holen:
$customers = App\Customer::all();
Einen Kunden holen mit der Datenbank ID 5
$customer = App\Customer::find(5);
Ein PDF würde ich jetzt nicht in der Datenbank speichern. Also dann doch eher im Filesystem.
Hallo Dirk, ich versuchs mal 🙂
Ich habe die Kunden so angelegt wie du oben die Produkte – mit dem Crud System.
Wie kann ich denn aber dem Kunden das PDF zuordnen? Ich hatte gedacht das ich einfach ein Verzeichnis erstelle während ich den Kunden erstelle. Zum Beispiel:
uploads/KUNDENID
und dort dann das PDF reinlege. Dann sollen alle Dokumente in diesem Verzeichnis ausgelesen werden.
Hast du da eine Idee?
Hallo,
Erstmal vielen Dank für dein Tutorial. Soweit hat bei mir auch alles geklappt, man sieht die Produkte auf der Produkt seite.
Jetzt aber meine Frage wie schafft man es diese Produkte auch auf eine Index seite anzeigen zu lassen.
Ich würde gern auf der index seite einen Slider machen bei dem die letzten x Produkte angezeigt wird.
Ich bekomme aber dann immer den Fehler Undefined variable:
Wie kann man das beheben?
Danke Dirk für das gute Tutorial
Allerdings fehlt das Delete form in der Liste ich werde das wohl erstellen müssen, da ich ohne „action“ kein Löschen ausführen kann.
Hier ist eine Lösung in index.blade.php einfügen
@foreach($products as $product)
id }}“>{{ $product->name }}
{{ $product->description }}
{{ number_format(($product->price/100), 2) }} CHF
id }}“>
@method(‚delete‘)
@csrf
@endforeach
Whoops kam nich alles mit!
@foreach($products as $product)
id }}“>{{ $product->name }}
{{ $product->description }}
{{ number_format(($product->price/100), 2) }} CHF
id }}“>
@method(‚delete‘)
@csrf
@endforeach
id }}“>
@method(‚delete‘)
@csrf
Hallo Dirk,
sehr schöner Beitrag, habe schon dein Blog durchstöbert und doch das ein oder andere neue dazugelernt.
Das ich die Migration, das Model wie auch den Controller gleichzeitig erstellen kann war mir neu.
Danke für den Beitrag