Ein Business-Netzwerk mit Laravel erstellen - Laravel Einstiegstutorial Teil 3

Ein Business-Netzwerk mit Laravel erstellen - Laravel Einstiegstutorial Teil 3

Es ist immer gut, alte Stricke abzureissen. Wir fangen in diesem Laravel-Tutorial einfach mal von vorne an und werden ein ECHTES Laravel-Projekt erstellen. Und dabei handelt es sich nicht um so etwas sinnloses, wie einen Terminkalender. Wir schreiben unser eigenes soziales Netzwerk namens Jobskills. Warum kleine Projekte, wenn man so richtig groß denken kann?! Genau so sehe ich das auch. Das Tutorial hier richtet sich an Leute, die bereits schon PHP-Webseiten umgesetzt haben. Außerdem setze ich voraus, dass Du einen Webserver konfigurieren kannst, mindestens also weißt, wie man Xampp installiert.

Genug geschwafelt, starten wir unser Job-Netzwerk!

Als ich mit diesem Tutorial anfing, war Laravel in Version 6.X die aktuelle Laravelversion. Das meiste wird sicherlich auch in Laravel 7 greifen, aber verifiziert ist das alles mit Laravel 6 und wird hier auch tadellos funktionieren.

Installationen von notwendigen Programmen

Dass PHP bei dir läuft, davon gehe ich aus. Auch einen Datenbankserver besitzt du.

Composer

PHP-Projekte inkludiert man sich heute nicht mehr wild zusammen. Genau so ist es mittlerweile so, dass man viele kleine PHP-Klassen nicht mehr irgendwo herunterlädt und dann in einen Ordner "plugins" legt und nachher gar nicht mehr weiß, welche Klassen man wo importieren muss. Heute gibt es Programme wie Composer, die es dir ermöglichen, diverse PHP-Klassen direkt über Kommandozeile zu laden. Dabei achtet Composer sogar darauf, dass alle möglichen Abhängigkeiten erfüllt werden. Wenn die Klasse "warenkorb" zum Beispiel die Klasse "artikel" vorraussetzt, wird die Klasse direkt mitgeladen. Ich kann nicht alle Funktionen von Composer beschreiben, dafür gibt's hier eine sehr umfangreiche Dokumentation. Dort wird auch ziemlich lässig beschrieben, was Composer noch alles kann und wofür es gut ist. Nicht zuletzt musst du Composer sowieso installieren. Also rufe die Download-Seite von Composer auf und führe die dort genannten Schritte durch. Windows-User haben es hier relativ einfach. Der Installer legt Composer sauber in den Pfad und globale Pakete funktionieren im Regelfall auch out-of-the-box. Die meisten Linuxdistributionen sind auch gut aufgestellt: Composer gibts meistens direkt über die jeweiligen Paketquellen.

NodeJS/NPM

Bitte installiere dir auch NodeJS. Mit NodeJS kriegst du auch NPM dazu. Laravel nutzt NPM oder auch YARN für das Javascript-Paketmanagement.

Ein Laravelprojekt initialisieren

Wenn Composer und Node nun ordnungsgemäß funktionieren, öffnest du eine Eingabeaufforderung. Ich werden übrigens "Shell" oder "Terminal" dazu sagen. Eingabeaufforderung nennt nur Windows das und ich versuche, das Tutorial so neutral wie möglich zu halten.

Öffne also das Terminal und wechsle in deinen Webordner. In Linux ist das /var/www bzw. in Windows oft xampp/htdocs

Starte dann folgenden Befehl

composer create-project laravel/laravel jobskills 6.0

Composer startet nun eine Litanei von Texten und es wird der Ordner jobskills erstellt.

Laravel legt los

Den Webserver konfigurieren (Roadrunner)

Damit wir unser Projekt nun direkt aufrufen können, müssen wir Apache beibringen, die index.php aus dem Verzeichnis jobskills/public zu laden. Also legen wir uns für dieses Projekt einen virtuellen Host an. Das ist die übliche Vorgehensweise bei solchen Projekten. Du kannst auch den Laravel-Webserver selbst benutzen oder sogar auch direkt mit einem Loadbalancer entwickeln. Für unsere Zwecke reicht der Vhost aber aus. Nicht zuletzt kannst du auch den Webserver von Laravel selbst nutzen, das hat aber so seine Nachteile, unabhängig davon ist es auch langsam.

Für mein Projekt verwende ich nun Roadrunner. Der Vorteil ist, dass ich im Grunde genommen nix besonders konfigurieren muss. Ich installiere einfach Roadrunner über

composer require spiral/roadrunner
  
./vendor/bin/rr get-binary

Der Webserver wird nun zu meinem Projekt dazu gepackt. Da Roadrunner Laravel nicht direkt unterstützt, fügen wir noch eine Roadrunner-Laravel-Brücke hinzu.

composer req updg/roadrunner-laravel

Und jetzt stellen wir den Roadrunner-Server so ein, dass die Bridge geladen wird.

<php
// worker.php
require __DIR__ . "/vendor/autoload.php";
  
$bridge = new \updg\roadrunner\laravel\Bridge();
$bridge->start();

Nun müssen wir noch eine Datei namens .rr.yaml erstellen und das hier da rein schreiben:

http:
  address:         0.0.0.0:8080
  workers.command: "php worker.php"
static:
  dir: 'public'

Anschließend starten wir den Webserver durch die Eingabe von rr serve und rufen localhost:8080 auf. Vergiss den Eintrag "static:" nicht, weil sonst die Javascripts/CSS-Daten nicht geladen werden

Mockups und Routen

Aktuell sieht die Seite so aus:

Laravel Standard-Seite

Wir wollen erst einmal definieren, wie die verschiedenen Bereiche unseres Business-Netzwerkes aussehen. Wir erstellen also ein paar Routen, Mockups und Designs, um die Seiten irgendwie präsentieren zu können. Ganz nebenbei legen wir noch fest, wie die Seitenstruktur aussehen könnte. Wir tun erst mal so, als wäre das System offen wie ein Scheunentor. Mit geschlossenen Bereichen befassen wir uns später. Wir wollen erst einmal nur sehen, wie die Website aussehen könnte.

Das Grundlayout

Wir legen fest, wie die ganze Seite im Kern aussehen soll. Oben gibt's eine einfache Menüstruktur. Je nach Wunsch kann der Hauptbereich aus zwei oder drei Spalten bestehen und abgeschlossen wird das alles von einem Footer. Wie bei allen größeren sozialen Netzwerken etabliert, ist die Startseite normalerweise bestehend aus einem Profilbereich, einem Newsfeed und einer Spalte mit weiteren Informationen. Das wird unsere Startseite. Ich gebe zu, ich kenne mich mit vue.js noch nicht so richtig aus, ich starte mit einem Bootstrap-Template.

Zuerst installieren wir Bootstrap unter Laravel

composer require laravel/ui
php artisan ui bootstrap --auth
npm install
npm run dev

Wir definieren, dass Laravel ein Userinterface mitinstallieren soll. Anschließend sagen wir, dass es Bootstrap sein soll und dass Laravel uns auch schon einmal die Routen (dazu später mehr) und Templates (auch dazu später mehr) für ein Login aufbauen soll. Was passiert hier: Composer zieht das Userinterface-Paket von Laravel. Anschließend legen wir fest, dass wir Bootstrap verwenden wollen und dass wir ein Grundgerüst für ein Login brauchen. Der NodeJS Package Manager installiert nun alle benötigten Pakete und wir generieren unsere CSS und Javascript-Dateien.

Interessanterweise hat Laravel uns auch schon die Login-Seite erstellt. Sieh dir http://localhost:8080/login an und staune.

Die von Laravel generierte Login-Seite.

Aktuell interessiert uns das aber herzlich wenig. Wir wollen unser Design machen. Zuerst legen wir fest, wie das Haupttemplate aussehen soll.

main.blade.php

Ich weiß nicht, wie ihr das macht. Ich will immer erst einmal sehen, wie eine Website aussieht. Also bau ich zuerst mal ein Template zusammen und modularisiere das Ding anschließend. Im Ordner /resources/views/layouts/ erstellen wir uns die Datei main.blade.php, die später unser generelles Layout bestimmen soll. Beachte bitte, dass hier viele Dinge später rausfliegen und/oder sogar neu geschrieben werden müssen.

<!doctype html>
<html lang="de">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link rel="stylesheet" href="{{asset('css/app.css')}}">
        <title>Document</title>
    </head>
    <body>
        <nav class="navbar navbar-expand-lg navbar-light bg-light">
            <a class="navbar-brand" href="#">Jobskills</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
            aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav">
                    <li class="nav-item active">
                    <a class="nav-link" href="#">Feed<span class="sr-only">(current)</span></a>
                    </li>
                    <li class="nav-item">
                    <a class="nav-link" href="#">Messages</a>
                    </li>
                    <li class="nav-item">
                    <a class="nav-link" href="#">Friends</a>
                    </li>
                </ul>
            </div>
        </nav>
        <div class="container">
            <div class="row">
                <div class="col">
                    1 of 2
                </div>
                <div class="col">
                    2 of 2
                </div>
            </div>
            <div class="row">
                <div class="col">
                    1 of 3
                </div>
                <div class="col">
                    2 of 3
                </div>
                <div class="col">
                    3 of 3
                </div>
            </div>
        </div>
    </body>
</html>

Tatsächlich ist das erstmal unser Layout. Jetzt wollen wir erreichen, dass genau DIESER View (so heißen die Templates bei Laravel) und wenn du in die Link rel-Zeile guckst, haben wir sogar schon eine Blade-Template-Variable verwendet

Intermezzo: Routen

Wir wollen, dass genau dieser View geladen wird, wenn wir localhost:8080 aufrufen. Das kann ja nicht so schwer sein. Tatsächlich steuert Laravel die Routen (also das, was der User tatsächlich aufruft) über ein einfaches PHP-Skript. Streng gesagt gilt: Wenn es für irgend etwas keine Route gibt, existiert es nicht und darf deshalb nicht aufgerufen werden. Öffne deshalb die Datei /routes/web.php und verändere die folgenden Bereiche:

Route::get('/', function () {
      return view('welcome');
  });

Wir verändern das in:

Route::get('/', function () {
      return view('layouts.main');
  });
3-Spaltiges Layout mit Kopfmenü

Wie du siehst, wird jetzt schon unser Design geladen. Das war doch schon einmal relativ einfach. Wir können unser Blade-Template jetz so anpassen, dass es aussieht, wie eine richtige Seite eines sozialen Netzwerkes. Da es sich hier um einfaches HTML handelt, werde ich nicht jeden einzelnen Schritt erklären. Ich will einfach nur, dass die Seite entsprechend des nachfolgenden Screenshots aussieht. Den Quellcode für das fertige Template könnt ihr euch unter folgendem Link genauer ansehen (Boostrap Quellcode). Letztendlich ist es aber egal, wie du die Views aufbaust.

Erster Entwurf des Templates. Nicht schön, aber irgendwo müssen wir ja anfangen.

Was genau haben wir bei dem Intermezzo gemacht? Wir haben Laravel mitgeteilt, dass es direkt den view namens main zurückgeben soll, der sich im Ordner layouts befindet. Einfach oder? Mit dieser ersten Route können wir zumindest schonmal unser Design zusammenstellen und haben direkt auch etwas, was man einem potentiellen Kunden zeigen kann.

Unser erster Controller

Laravel verfolgt das MVC-Prinzip. Es gibt ein Modell, einen View und einen Controller. Wie ein View aufgesetzt und aufgerufen wird, habe ich erklärt. Beschäftigen wir uns nun mit dem Controller. Unser Controller hat die Aufgabe, unser Standard-Template darzustellen. Zuerst erstellen wir unseren Controller, indem wir im Terminal folgenden Befehl einhacken.

php artisan make:controller StartController --resource

–resource legt fest, dass Laravel in den Controller schon einmal ein paar Standard-Funktionen reinschreiben soll.

Wir öffnen nochmal die web.php aus dem Routes-Ordner und ändern noch einmal die Route von vorhin:

Route::get('/', function () {
      return view('layouts.main');
  });

Wir ersetzen das durch den folgenden Code:

Route::get('/', 'StartController@index');

Wenn wir die Seite nun aktualisieren, ist sie leer und nichts passiert. Logisch, weil jetzt unser Controller geladen wird, der keinen View zurück gibt. Wir müssen also unseren Controller öffnen und ihm mitteilen, bitte den View zu laden:

Öffne die Datei app/Http/Controllers/StartController.php und vergleiche das nochmal mit der Route. Wir haben gesagt, sobald per GET das Hauptverzeichnis der Website aufgerufen wird, soll StartController geladen werden. Das @index legt fest, dass die Methode INDEX geladen werden soll. Tja, dann schreiben wir doch einfach dort rein, dass der View layouts.main geladen werden soll.

public function index()
    {
        return View('layouts.main');
    }

Wenn wir nun wieder im Browser die Seite aktualisieren, wird unser Template/Design von vorhin wieder angezeigt.

Das erste Modell

Da unser View läuft, wir einen ersten Controller gemacht haben und unser Webserver die Seite schön ordentlich darstellt, sollten wir nun beginne, wirklich dynamische Daten in unser Template einzubinden. Wir leben in spannenden Zeiten, also befassen wir uns doch heute mal mit Fakenews. Wir tauschen unsere Newscontent blabla-Blöcke durch Beiträge aus den News aus.

Ich selbst verwende an dieser Stelle nun MariaDB als Datenbankserver. Du kannst aber auch SQLite oder auch MS-SQL-Server verwenden, wenn du willst. Zuerst müssen wir die Daten für unsere Anbindung in die .env-Datei eintragen.

Einrichtung der Datenbankverbindung

Wie oben erwähnt, öffnest du jetzt die .env und hinterlegst die Servereinstellungen.

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

Die Datenbank (in dem Fall "laravel") erstellst du am besten schon einmal über SQL direkt oder über ein Frontend für deinen MySQL-Server. Was wir uns jetzt direkt abgewöhnen, ist das erstellen und bearbeiten von Tabellen über phpmyadmin oder ähnlichen Tools. Die Pflege der Felder, die Anzahl der Tabellen und die gesamte Datenbankstruktur wird in modernen PHP-Anwendungen allerdings auch über PHP gemacht. Der Grund ist: So kann jeder Entwickler mit seiner Datenbank arbeiten und alle verwenden dieselben Strukturen, die dann eben auch im VCS wie GIT oder SVN mit übernommen werden können. Du sparst dir also, SQL-Dateien mitliefern zu müssen. Alles ist PHP und alles kommt aus einem Guss.

Wir erstellen eine Tabelle und ein Modell

Niemand ist fauler, als Programmierer. Wir erstellen also direkt ein Modell, eine Migration, einen Seeder und auch eine Factory.

php artisan make:model NewsFeed -a.

Laravel erstellt nun einen ganzen Schwung Dateien, die wir uns zumindest teilweise mal anschauen wollen. Zuerst gegen wir mal in den Ordner database und stellen fest, dass wir hier eine neue Datei haben, die so heißt, wie das heutige Tagesdatum, gefolgt von einem Timestamp, also in etwa so YYY_MM_DD_123456_create_news_feeds_table.php. Wenn wir dieses Skript öffnen, steht dort in etwa folgender Code drin:

<?php
  
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
  
class CreateNewsFeedsTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('news_feeds', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }
  
    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('news_feeds');
    }
}

Die function up() legt fest, dass Schema::create unsere Tabelle erstellt, die zumindest schon mal aus dem Feld “id” und irgendwelchen Timestamps bestehen soll. Die function down() hingegen scheint irgendwie zu definieren, dass Schema::dropIfExists offenbar irgend etwas löschen soll. Wir wollen aber ja News hinzufügen, also erscheint es nur logisch, in die up()-Methoden irgendwelche Dinge hinein zu schreiben. News bestehen in der Regel aus einer Headline einem Newstext, einem Verweis auf den Autor und eventuell noch aus einem Artikelbild. Ich würde sagen, damit kann man doch schonmal starten.

[...]
public function up()
{
    Schema::create('news_feeds', function (Blueprint $table) {
        $table->bigIncrements('id'); // Automatisch hochzählende ID
        $table->text('headline'); // Kurzer Text
        $table->longText('newstext'); // Langer Text
        $table->bigInteger('author'); // Das wird die Verknüpfung zum Autor (Usertabelle)
        $table->text('imageUrl'); // Pfad zum Bild
        $table->timestamps(); // Erstellungs / Update-Datum
    });
}

Die freundliche Laravel-Dokumentation beschreibt dir, welche Feldtypen es gibt und wie man diese Feldtypen benutzt. Wenn wir die Datenbank nun migrieren wollen, also die Tabellenstruktur in MySQL übernehmen wollen, führen wir folgenden Befehl aus

php artisan migrate

Achtung Stolperstein: Unter Xampp habe ich regelmässig Probleme beim Migrieren. Das liegt offenbar an der verwendeten MariaDB-Version. Es kommt folgende Fehlermeldung:

1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`))

Dieser Fehler lässt sich leicht beheben, die Ursache ist im Zeichensatz zu finden und nicht besonders dramatisch. Öffne folgende Datei und bearbeite die Boot-Methode:

app/Providers/AppServiceProvider.php

<?php
  
namespace App\Providers;
  
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
  
class AppServiceProvider extends ServiceProvider
{
    /**
    * Register any application services.
    *
    * @return void
    */
    public function register()
    {
        //
    }
  
    /**
    * Bootstrap any application services.
    *
    * @return void
    */
    public function boot()
    {
        Schema::defaultStringLength(191);
    }
}

Danach sollte die Migration problemlos durchlaufen, allerdings solltest du nun

php artisan migrate:fresh

eingeben, damit die Tabellen neu generiert werden und bereits existierende Tabellen überschrieben werden.

Migrationen werden erstellt

In deinem Datenbankfrontend kannst du nun sehen, dass wir diverse Tabellen haben. Alle Tabellen sind mehr oder weniger leer, bis auf die migrations-Tabelle, die uns für den Moment aber nicht interessieren soll, wir wollen mit jetzt unsere Datenbank füllen. Wir brauchen für unser soziales Netzwerk mindestens einen User und eine große Anzahl von Newsbeiträgen, die von diversen anderen Benutzern kommen.

Seeds / Testdaten / Fakedaten

Gerade wenn man mit Laravel anfängt, wird man vom folgenden Kapitel komplett erschlagen. Wir arbeiten jetzt mit Fabrik-Funktionen, Fake-Daten, nebenbei verwenden wir schon Eloquent-Models aus Laravel und wir führen sogar schon Leseoperationen aus. Ich habe nie behauptet, dass das Tutorial unverschämt einfach wird, aber gerade die folgenden Sätze enthalten wahnsinnig viele Informationen. Es ist wichtig, den Arbeitsschritten chronologisch zu folgen, denn wir springen hier mindestens zwischen 4 Skripts immer wieder hin und her und wir arbeiten parallel auch noch auf der Kommandozeile.

Zuerst erstellen wir uns nun 100 Fake-Benutzer und 100 Fake-Newsbeiträge, beginnen wir mit dem Fake-Benutzer-Seeder.

php artisan make:seeder UsersTableSeeder

Laravel erstellt nun die Datei /database/seeds/UsersTableSeeder.php. Der Code sieht in etwa so aus:

<?php
  
use Illuminate\Database\Seeder;
  
class UsersTableSeeder extends Seeder
{
    /**
    * Run the database seeds.
    *
    * @return void
    */
    public function run()
    {
        //
    }
}

Es gibt in Laravel sogenannte Factories, die automatisch Testdaten erstellen können. Unsere Benutzerfabrik kann uns also gefakte Benutzer erstellen. Gucken wir uns den Quellcode der /database/factories/UserFactory.php einmal genauer an, zumindest die Methode, die aufgerufen wird:

<?php
[...]
$factory->define(User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
        'remember_token' => Str::random(10),
    ];
});

Wir sehen, dass eine Faker-Klasse aufgerufen wird. Der Faker ist ein spannendes Stück Software, das realistisch aussehende Daten generiert. Wenn ich eine Emailadresse faken will, dann sollte diese Mailadresse zumindest dem entsprechen, was wir so als Emailadresse bezeichnen würden. Die

Was genau ist das? Die User-Klasse wird aufgerufen und $faker erstellt jeweils einen Namen, eine Emailadresse und so weiter. Wir springen jetzt nochmal in den UsersTableSeeder.php zurück.

public function run()
{
    // Erstelle 100 Benutzer
    factory(App\User::class, 100)->create();
}

Die Factory-Funktion ruft nun die Fabrik auf und erstellt so 100 Benutzer. Für unseren Test könnten wir uns jetzt als irgendwer dieser Benutzer einloggen, aber aktuell haben wir ja noch keine dynamischen Daten / News hinterlegt. Wir brauchen also noch Fakenews und die hinterlegen wir in der NewsFeedFactory.php und ich versuche, den Code so verständlich wie möglich zu halten:

<?php
  
/** @var \Illuminate\Database\Eloquent\Factory $factory */
  
use App\NewsFeed;
use Faker\Generator as Faker;
  
$factory->define(NewsFeed::class, function (Faker $faker) {
    $users = App\User::all()->pluck('id')->toArray();
  
    return [
        'headline' => $faker->sentence,
        'newstext' => $faker->realText(500),
        'author' => $faker->randomElement($users),
        'imageUrl' => $faker->url,
        'created_at' => now(),
        'updated_at' => now()
    ];
});

Die folgende Zeile wird dir definitiv seltsam vorkommen:

$users = App\User::all()->pluck('id')->toArray();

Da wir bereits 100 Benutzer erstellt haben, laden wir hier ein Array aller User und schreiben dieses Array in die Variable $users rein. Anschließend definieren wir, dass die Fabrik eine Headline (ein gefakter Satz), einen newstext und als Autor einen zufälligen Wert aus der Authorenliste generieren soll. Die ImageURL ist eine willkürliche URL, als Zeitstempel verwenden wir das aktuelle Datum und die aktuelle Uhrzeit.

Nun öffnen wir die Datei NewsFeedSeeder.php und sagen dem Seeder, dass er doch bitte auch 100 Newsbeiträge schreiben soll. Die Vorgehensweise ist ähnlich dem Userseeder oben, die Run-Methode wird angepasst:

public function run()
{
        factory(App\NewsFeed::class, 100)->create();
}

Wir lösen nun beide Seeds aus und müssen dafür die Datei /database/DatabaseSeeder.php öffnen. Wir überarbeiten die run()-Methode in dieser Klasse:

public function run()
{
    $this->call(UsersTableSeeder::class);
    $this->call(NewsFeedSeeder::class);
}

Wir haben jetzt 100 Benutzer und 100 Newsbeiträge, die zufällig von irgendwelchen Benutzern geschrieben wurden. Zum Testen ist das absolut perfekt.

News im Template anzeigen

Wir schreiben eine Funktion, die uns alle News im Template anzeigt. Dazu öffnen wir nun einmal unseren StartController.php und gehen in die Index-Funktion rein.

use App\NewsFeed; // Oben einfügen
  
[...]
public function index()
{
    $News = NewsFeed::all();
  
    return View('layouts.main',['News'=>$News]);
}

Wenn wir nun F5 drücken, passiert erstmal nichts. Was passiert hier? Wir sagen dem Eloquent-Modell, dass wir ALLE News auslesen wollen und in die Variable $News laden möchten. Anschließend übergeben wir die Variable $News an das Template in der Variable ‘News’, was ziemlich bescheuert ist, weil es diese Variable im Template noch gar nicht gibt.

Öffnen wir nun also nochmal unsere resources/views/layout/main.blade.php. Bitte beachte INSBESONDERE den Bereich, wo ich @foreach geschrieben habe.

<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport"
    content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{{asset('css/app.css')}}">
<title>Document</title>
</head>
<body>
    <nav class="navbar navbar-expand-lg bg-dark navbar-dark">
        <a class="navbar-brand" href="#">Jobskills</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarNav" aria-controls="navbarNav"
            aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav">
                <li class="nav-item active"><a class="nav-link" href="#">Feed<span
                        class="sr-only">(current)</span></a></li>
                <li class="nav-item"><a class="nav-link" href="#">Messages</a></li>
                <li class="nav-item"><a class="nav-link" href="#">Friends</a></li>
  
            </ul>
        </div>
    </nav>
    <div class="container">
        <div class="row">
            <div class="col">
                <div class="card">
  
                    <div class="card-body">
                        <h2 class="card-title">Username Lastname</h2>
                        Occupation at Company
                    </div>
                </div>
  
            </div>
            <div class="col-7">
            @foreach($News as $Item)
                <div class="card">
                    <div class="card-body">
                        <h3 class="card-title">{{$Item->headline}}</h3>
                        {{$Item->newstext}}
  
                    </div>
                </div>
            @endforeach
  
            </div>
            <div class="col">
                <div class="card">
                    <div class="card-body">
                        <h3 class="card-title">Happening in your network</h3>
                        <ul class="list-group">
                            <li class="list-group-item"><a href="#">Laravel Tutorial</a></li>
                            <li class="list-group-item"><a href="#">Laravel Tutorial</a></li>
                            <li class="list-group-item"><a href="#">Laravel Tutorial</a></li>
                        </ul>
  
                    </div>
                </div>
  
            </div>
        </div>
    </div>
    <script src="{{asset('js/app.js')}}"></script>
</body>
</html>

Wie du siehst, ist hier eine Template-Variable in einer Foreach-Schleife übergeben. Hier werden ALLE 100 Newsbeiträge angezeigt. In der Praxis würde man das so allerdings nicht machen, weil wir irgendwann ja bei ein paar hundert Millionen Beiträgen ankommen würden. 100 News. So einfach geht das

News seitenweise im Template anzeigen

Jetzt wirds geil. Wir wollen nur 10 News anzeigen lassen und dabei eine Blätternavigation hinterlegen. Dazu verändern wir noch einmal die index()-Methode im StartController und schreiben diese um:

public function index()
{
    $News = NewsFeed::paginate(2);
  
    return View('layouts.main',['News'=>$News]);
}

Anschließend gehen wir in das Template und schreiben unter @endforeach noch folgendes kleines Snippet:

{{$News->links()}}
100 News, aufgeteilt in jeweils 2 Stück

Review der oben gemachten Tasks

  • Wir haben ein Eloquent-Modell, eine Migration und einen Seeder erstellt: php artisan make:model NewsFeed -a
  • Wir haben einen Controller erstellt: php artisan make:controller StartController
  • Wir haben Faker genutzt, um unseren Seeder zu befüllen.
  • Wir haben im NewsSeeder alle User ausgelesen, die unser User-Modell hergibt
  • Wir haben das Template angepasst und mit @foreach und @endforeach sogar schon Schleifen verwendet.

Tatsächlich reicht das alles schon, um Laravel vernünftig nutzen zu können, aber ich möchte und muss dir natürlich noch viel mehr mitgeben.

Models vs. SQL - Laravel Eloquent

Laravel nennt sich “Framework for Web Artisans” und nichts könnte treffender sein: Laravel für Handwerker, für Leute, die schnelle und messbare Ergebnisse haben wollten. Und dazu gehört eben, dass das Framework dir Arbeit abnehmen soll und vor allem das macht, was ein PHP-Coder kann. PHP. Nicht SQL. Die meisten PHP-Coder können natürlich SQL und ich bin auch nicht derjenige, der denen das verbieten möchte. Spätestens bei Joins wird’s manchmal aber schon ein wenig schwieriger aber lustigerweise ist gerade das mit Laravel echt simpel.

Eloquent nennt sich das ORM bei Laravel. Die Idee ist, die Datenbanktabellen als Objekte abzubilden und an diese Daten auch über PHP-Funktionen dran zu kommen. Ich versuche mal, SQL und Eloquent direkt zu vergleichen. Bitte beachte, dass das natürlich in Klassen hinterlegt sein muss

SQL: Gib mir alle News (mysqli)

$mysqli = new mysqli('127.0.0.1', 'your_user', 'your_pass', 'your_database');
$sql = 'SELECT * FROM NewsFeed';
$result = $mysqli->query($sql);
while($data = $result->fetch_assoc()) {
    $rows[] = $data;
}
print_r($rows);

Eloquent: Gib mir alle News

<?php
/* NewsController */
use App\NewsFeed;
$rows = NewsFeed::all();
dump($rows);

Wie geht’s hier weiter?

Wir legen in Zukunft JOINS an. Das wird gut :)


Autor: Marcel Schindler
Datum: 20.02.2020
Tags: php tutorial npm laravel
Kategorie: Laravel