Erstellt ein Model, je nachdem ob das Flag -m
mitgegeben worden wurde mit oder ohne Migration.
php artisan make:model Book -m
Erstellt einen Controller, je nachdem ob das Flag -r
mitgegeben worden wurde, wird dieser als Resource-Controller erstellt.
php artisan make:controller BookController -r
Models repräsentieren unsere Tabellen in der Datenbank aus objektorientierter Sicht.
Book::create([
"name" => "Harry Potter und der Stein der Weisen",
"author" => "J.K. Rowling",
"isbn" => "3551557411",
]);
Name | Resource-Controller Methode | HTTP-Methode | PFAD | Beschreibung |
---|---|---|---|---|
Browse | index | GET | /books | Zeigt alle Resourcen an (Teil der REST-Konvention) |
Read | show | GET | /books/{id} | Zeigt eine Resource mit der angegebenen ID (Teil der REST-Konvention) |
Edit | update | PUT/PATCH | /books/{id} | Editieren einzelner oder aller Daten einer bereits bestehenden Resource (Teil der REST-Konvention) |
Add | store | POST | /books | Erstellen einer Resource (Teil der REST-Konvention) |
Delete | destroy | DELETE | /books/{id} | Löschen einer Resource (Teil der REST-Konvention) |
--- | create | GET | /books/create | Formular zum erstellen von der Resource (Laravel spezifisch 🐠) |
--- | edit | GET | /books/{id}/edit | Formular zum editieren einer Resource (Laravel spezifisch 🐠) |
Was | Wie | Beispiel |
---|---|---|
Controller | singular | ArticleController |
Route | plural | books/1 |
Named route | snake_case with dot notation | users.show_active |
Model | singular | User |
hasOne or belongsTo relationship | singular | articleComment |
All other relationships | plural | articleComments |
Table | plural | article_comments |
Pivot table | singular model names in alphabetical order | article_user |
Table column | snake_case without model name | meta_title |
Model property | snake_case | $model->created_at |
Foreign key | Model Name im singular mit _id suffix | author_id |
Migration | snake_case_mit_datum_und_uhrzeit | 2017_01_01_000000_create_articles_table |
Method | camelCase | getAll |
Method in resource controller | table | store |
Method in test class | camelCase | testGuestCannotSeeArticle |
Variable | camelCase | $articlesWithAuthor |
Collection | descriptive, plural | $activeUsers = User::active()->get() |
Object | descriptive, singular | $activeUser = User::active()->first() |
Config and language files index | snake_case | articles_enabled |
View | kebab-case | show-filtered.blade.php |
Config | snake_case | google_calendar.php |
Contract (interface) | adjective or noun | Authenticatable |
Trait | adjective | Notifiable |
Beziehungen werden in Laravel in den Models erstellt.
Beispielsweise kann ein Bürger genau eine Passnummer haben. Verknüpfung im Model des Bürgers (citizen):
class Person extends Model {
public function pass() {
return $this->hasOne('Pfad zum Model\pass');
}
}
Verknüpfung im Model Personalausweisnummer (pass):
class Pass extends Model {
public function person() {
return $this->belongsTo('Pfad zum Model\citizen');
}
}
Wichtig hierbei ist, dass man nicht zweimal hasOne nehmen darf.
Bei einer 1:N-Beziehung gibt es die Methoden "belongsTo" und "hasMany". Hier ein Beispiel aus dem Skript mit "Books" und "Publisher". Ein Buch kann nur einen Publisher haben, umgekehrt kann aber ein Publisher mehrere Bücher veröffentlichen. Im Book-Model muss es dann wie folgt geschrieben werden:
class Book extends Model {
public function publisher() {
return $this->belongsTo('App\Book');
}
}
Es wird also gesagt, dieses Buch hat genau einen Publisher durch die belongsTo-Methode.
Im Publisher-Model sieht es dann wie folgt aus:
class Publisher extends Model {
public function books() {
return $this->hasMany('App\Book');
}
}
Wichtig ist, dass in der Migration-File der Tabelle, in der der Fremdschlüssel steht, auch eine entsprechende Spalte erstellt wird. In der Books-Migration-File muss also für den Publisher noch eine entsprechende Spalte erstellt werden:
$table->unsignedBigInteger('publisher_id');
//Die publisher_id wird nun noch mit der ID aus der Tabelle Publisher verknüpft
$table->foreign('publisher_id')->references('id')->on('publisher');
Das Grundprinzip ist immer das selbe: $table->foreign("Spaltenname")->references("Primärspalte aus zu verknüpfender Tabelle")->on("Tabellenname welche verknüpft wird");
Bei N:M-Beziehungen gibt es nur eine Methode, welche in beiden Models verwendet werden muss. Sie heißt "belongsToMany". Ein Autor kann z.B. mehrere Bücher haben, ein Buch kann aber auch gleichzeitig mehrere Autoren haben (z.B. Handbücher für Programmiersprachen). im Author-Model ist der Code dann wie folgt:
class Author extends Model {
public function books() {
return $this->belongsToMany('App\Book');
Auf der Gegenseite im Book-Model ist der Code (fast) der selbe:
class Book extends Model {
public function authors() {
return $this->belongsToMany('App\Author');
Bei N:M-Beziehungen muss man immer einen Hilfstabelle erstellen, welche die zwei Primärschlüssel entgegen nimmt. Sehr wichtig ist, dass diese Migration-File erst nach den zwei Migration-Files für die Books und die Authors ausgeführt wird! In der Hilfstaballe werden dann diese Spalten erstellt:
$table->unsignedBigInteger('author_id');
$table->foreign('author_id')->references('id')->on('authors');
$table->unsignedBigInteger('book_id');
$table->foreign('book_id')->references('id')->on('books');
Es handelt sich hierbei um Beispiele. Durch den Befehl -m wird ja für ein Model die Migration-File automatisch erstellt, allerdings wird man ggf. in der Prüfung auch die Klasse erstellen müssen, daher sollte man folgendes können:
- Benennen der Klasse: class CreateUsersTable extends Migration
- Füllen der Funktion "up" Wichtig hier der Befehl: Schema::create('users', function (Blueprint $table)
- Je nach Angabe unterschiedliche Spalten erstellen
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
//Optional
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Die Person hat keine weiteren Abhängigkeiten (in diesem Beispiel). Im folgenden wird kurz beleuchtet, wie man Fremdschlüssel in der Migration erstellt.
Eine Person hat genau eine Passnummer, also muss in der Tabelle der Pässe, die ID der Person zu geordnet werden:
class CreatePassesTable extends Migration
{
public function up()
{
Schema::create('passes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
//Das ist der wichtige Teil hier!
$table->unsignedBigInteger('person_id');
$table->foreign('person_id')->references('id')->on('people');
});
}
Oben, beim erstellen der Tabellenbeziehungen wurde kurz schon auf das erstellen der Fremdschlüssel-Spalten eingegangen. Hier nun die ausführliche Version der 1:N-Beziehung zwischen Publisher (1) und Büchern (N):
class CreateBooksTable extends Migration
{
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('isbn');
//Wichtiger Teil: Erstellung der Spalte und Referenzierung auf die ID der Publishers
$table->unsignedBigInteger('publisher_id')->nullable();
$table->foreign('publisher_id')->references('id')->on('publishers');
$table->timestamps();
});
}
Auf der Gegenseite (der "1"-Beziehung) muss nichts gemacht werden.
Auch hier wurde bereits oben erwähnt, dass man bei einer N:M-Tabelle eine Zwischentabelle erstellt. Daher muss man für diese Beziehung keine Fremdschlüssel in den Tabellen erstellen, sondern nur in der Zwischentabelle. Die Zwischentabelle kann man entweder nach der Migration innerhalb einer zugehörigen Klasse machen (wie in diesem Beispiel) oder als seperate Migrations-Datei. Macht man eine sepearte Migrations-Datei, ist zu beachten, dass die zwei zugehörigen Tabellen vorher erstellt werden, sonst kommt es zu einem Fehler.
class CreateBooksTable extends Migration
{
public function up()
{
//Siehe oben
});
//Zwischentabelle mit den zwei Fremdschlüsselspalten!
Schema::create('author_book', function(Blueprint $table) {
$table->unsignedBigInteger('author_id');
$table->foreign('author_id')->references('id')->on('authors');
$table->unsignedBigInteger('book_id');
$table->foreign('book_id')->references('id')->on('books');
});
}
Notwendige Komponenten / Einstellungen:
- Route für get- und post-Aufrufe des Clients
- Controller mit passenden Funktionen
- Validierung direkt im Controller oder mit Hilfe einer FormRequest-Klasse
- Views (Blade-Templates) für das Formular und ggf. weiteren Ansichten
Formulare benötigen in der web.php zwei Routen. Im Beispiel möchten wir Events erstellen.
Route::get('/events', 'EventController@create')->name('event_create');
Route::post('/events', 'EventController@store')->name('event_store');
Im "EventController" müssen nun die zwei Funktionen "create" und "store gemacht werden:
public function create() {
return view('event_create');
}
Der View stellt uns ein Formular bereit, das so ausschauen kann:
<form method="POST" action="{{ route('event_store') }}" id="create-event-form">
<div>
<label for="name" control-label">Name</label>
<div>
<input id="name" type="text" name="name" value="{{ old('name') }}">
</div>
</div>
<div>
<button type="submit" class="btn btn-primary">{{ __('Speichern') }}</button>
</div>
</form>
Die wichtigen Elemente sind folgende:
- method="POST" -> damit sagen wir das es "abgesendet" wird
- action="{{ route('event_store') }} -> der View 'event_store' wird in der Methode "store" am ende returnt
- man braucht ein Label und den Input, sowie einen Button zum absenden
public function store(Request $request) {
$event = new \App\Event();
$event->name = $request->get('name');
$event->save();
return view('event_store')->with('event', $event);
}
Code in web.php
Route::get('/artists', function() {
return view('artists', ['artists'=>Artist::all()]);
});
// Mit dem Befehl Artist::all() werden alle Artisten, die in der Tabelle gespeichert sind abgerufen und im Array gespeichert
Code in dem View 'artists':
<ul>
@foreach($artists as $artist)
<li>{{$artist->name}}</li>
@endforeach
</ul>
Der Befehl @foreach lädt nun alle artists, die im Array gespeichert sind in die Variable $artist. Für jeden $artist wird dann der Name als Item einer Liste ausgegeben.
In diesem Beispiel wird über eine for-Schleife Artists erstellt und der Name, der an der jeweilgen Stelle steht, verwendet.
public function run()
{
$artists = ['Artist1', 'Artist2', 'Artist3', 'Artist4', 'Artist5', 'Artist6', 'Artist7'];
for($i = 0; $i < count($artists); $i++) {
factory(Artist::class)->create(["name" => $artists[$i]]);
}
}
}
Mit "count($artists)" wird die Anzahl der im Array gespeicherten Werte herausgefunden. Der Name wird in Verbindung mit einer Factory erstellt. Den Namen geben wir hier vor, alle anderen Daten werden aber mit einem faker erstellt (später dazu mehr).
Middleware kann vielseitig eingesetzt werden:
- Protokollierung
- Sicherheitsprüfungen
- Debugging
- Vereinheitlichung uvm.
Middleware funktioniert vor allem als eine Art Filter und überwacht die gesamte Kommunikation zwischen Client und Server
Middleware kann enntweder bei einer ankommenden Anfrage oder bei einer Antwort aktiv werden: Für Anfragen:
public function handle($request, Closure $next) {
//Filteranweisungen bla bla
return $next($request);
}
Für Antworten:
public function handle($request, Closure $next) {
$response = $next($request);
//Filteranweisungen
return $response;
}
Man kann einen Filter in der web.php auf eine Route registrieren:
Route::get("/", function () {
return "Welcome"
})->middleware("Name der Middleware");