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.

In diesem kleinen Projekt, werden noch keine Abhängigkeiten in der Datenbank berücksichtigt. Das Einbauen der Kategorien folgt in einem der weiteren Teile.
Wenn ich von „Meinem Design/Startseite“ spreche, erkläre ich damit mein Layout, was bei euch natürlich wieder anders aussehen bzw. gelöst werden kann.

Vorbereitung

Die Datenbank

Eine Tabelle 'content' mit den Spalten
id, title, description, teaser, imgpath, created_at

Eine Tabelle 'user' mit den Spalten
id, username, email, password, forename, familyname, created_at

Die Ordnerstruktur im Hintergrund
- | auth
- | css
- - | custom.css
- | img
- - | Bilder die auf der Seite statisch verwendet werden
- | inc
- - | login.inc.php
- | js
- | upload-img
- | index.php

Im Ordner auth werden alle Files erstellt, die nur über einen Login erreichbar sind.
Im Ordner css sollte logisch sein, welche Files hier rein kommen, das gleiche gilt für img‚ und js. 😉
Im Ordner inc speichere ich alle Files rein, die Code beinhalten, den ich öfter irgendwo brauche, wie zum Beispiel den Login zur Datenbank oder die Navigation.
Im Ordner upload-img speichere ich alle Bilder rein, die ich über mein kleines Backend hochlade.

Erstell auch einen Testeintrag in der 'content'-Tabelle in der Datenbank

inc/login.inc.php

Die login.inc.php beinhaltet die Verbindung zur Datenbank. Hierfür lege ich vier Variablen an für den Host, Passwort, User und Datenbanknamen
$host, $pw, $user, $db
Das MySQL Statement für die Verbindung zur Datenbank speichere ich ebenfalls in eine Variable ab. Achtung, die Reihenfolge ist wichtig und kann NICHT verändert werden. Diese Methode erwartet vier Parameter in genau der Reihenfolge.
$con = new mysqli($host, $user, $pw, $db);
Damit ich eine Meldung bekomme, falls die Verbingung nicht funktioniert, schreib ich noch ein kleines if-Statement:
if($con->connect_errno) {
printf("Connect failed: %s\n", $con->connect_error);
exit();
}

Die index.php

Die index.php besteht aus einer grundlegenden HTML Struktur. In meinem Beispiel (siehe linker Screenshot) binde ich Bootstrap ein und tausche hier auch gleich die jQuery Versionen aus. Wenn man Bootstrap von der offiziellen Seite einbindet, wird die jQuery Slim Version verwendet. Prinzipiell keine schlechte Idee, sofern man nicht mit Ajax arbeiten will. Daher den Link austauschen durch die minified Version von jQuery.
Außerdem arbeite ich gern mit Icons, weshalb ich mir den CDN Link für Fontawesome hole.
Um nicht die üblichen Verdächtigen bei den Schriften nehmen zu müssen, binde ich über Google Font zwei Schriften ein. Eine Handschrift für die Überschriften und eine gut lesbare (z.B.: Raleway, …). Das deklarier ich dann auch in meinem ‚css/custom.css‘.

Mein Design beginnt mit einem Slider von Bootstrap und Bildern von, da es ein Übungsprojekt ist, Unsplash (Achtung, die Bilder sollten für den Slider im Querformat sein und die selbe Abmessung haben sonst kann es sein, dass die Seite zu hüpfen anfängt), einem animierten Einführungstext (schöne Erklärung dazu von den Kulturbanausen) und den Wiki Einträge, dargestellt mit der Card Column von Bootstrap, die in einer Div-Box mit der Klasse container eingebettet ist.

Um die Daten aus der Datenbank laden zu können, muss das login.inc.php eingebunden werden. PHP hat hierzu die Funktion include();
include('inc/login.inc.php');

Jetzt zu den Datensätzen. Auf der Startseite benötigen wir vorerst mal die id, title, teaser, imgpath. Das Ergebnis wird in eine Variable gespeichert.

$result = $con->query("SELECT id, title, teaser, imgpath FROM content");

Mit var_dump($result); können wir uns anschauen was sich da drin befindet.
Hier seht ihr jetzt ein Objekt. Dieses Objekt zeigt, dass wir 4 Felder haben und (ich hab ein paar mehr Daten schon in der Datenbank) acht Datensätze vorhanden sind.

Um diese Datensätze anzuzeigen brauchen wir eine while-Schleife.
Mit fetch_assoc() wird eine Zeile aus dem Objekt abgerufen und als assoziatives Array in die Variable $entry abgespeichert.
Erklärungen zu den Unterschieden zu: PHP Mysql Fetch Association Vs Fetch Array Vs Fetch Object Performance Analysis

while($entry = $result->fetch_assoc()) { ... // Ausgabe ... }
Innerhalb der while-Schleife befindet sich eine Bootstrap Card.
Für die div-Box mit der Klasse card wird noch eine eindeutige ID für später benötigt. Dies wird erreicht, indem dem Attribut id die id aus der Datenbank mitgegeben wird: id="id-<?php echo $entry['id'] ?>"

Da nicht jeder Eintrag vielleicht ein Bild hat, prüfe ich vorher, ob ein Eintrag in der Spalte imgpath vorhanden ist: <?php if($entry['imgpath']) ?>

Wenn ja (Hinweis auf eine if-Verzweigung), kann ich das Bild einbinden: src="lexikon-img/<?php echo $entry['imgpath'] ?>"

Um das Modal mit den restlichen Informationen asynchron laden zu können, benutzen wir Ajax. Für den Trigger um das Script auslösen zu können, benutze ich eine Klasse die ich auf den Button lege. Zusätzlich übergebe ich mit dem Button eine data-id, später mehr dazu.
<button type="button" class="card-title btn ajaxModal" data-toggle="modal" data-id="<?php echo $entry['id'] ?>">

Außerdem möchte ich den Teaser aus der Datenbank in der Card ausgeben: <?php echo $entry['teaser']; ?>

Am Ende nicht vergessen, die Verbindung zur Datenbank wieder zu schließen:
<?php $con->close(); ?>

Details mit Ajax in ein Modal laden

Um die Daten aus der Datenbank anzuzeigen, ohne die Seite zu verlassen oder neu zu laden, benötigen wir zu Anfang das Grundgerüst eines Modals in der index.php. Jedoch nicht das ganze.

Für den Rest im Modal brauchen wir eine neue Datei: inc/loadModal.inc.php
Anmerkung: Falls ihr euch jetzt fragt, was das „inc“ zwischen Dateiname und Endung bedeutet… Es kennzeichnet das File in der Ordnerstruktur als „included“, also dass es irgendwo eingebunden wird. Wir sind aber in der index.php noch nicht ganz fertig.

Die Ajax-Magic

Das Ajax-Script schaut in seiner Grundstruktur eigentlich fast immer gleich aus…
Vor dem Script muss jQuery geladen werden. Sonst funktioniert der Spaß nicht.

Ein Beispiel für Ajax mit JSON zum Anschauen findet ihr auf itsolutionstuff.com
Ein weiteres Beispiel ohne JSON mit Erklärungen findet ihr findet ihr auf freecodecamp.org

Ajax (Asynchronous JavaScript and Xml) ist ein Konzept, das es Webanwendungen ermöglicht, neue Daten vom Server zu erhalten und/oder dem Server für die weitere Verarbeitung zu senden, ohne dass die Seite als Ganzes neu geladen wird.“
wiki.selfhtml.org am 03.05.2020 aufgerufen (Der Artikel ist eine gute Einführung in Ajax)

Das fertige Ajax

 

<script>
Damit jQuery erst ausgeführt wird, wenn alle notwendigen Ressourcen komplett geladen sind ist der Standardaufbau
$(document).ready(function() { /* jQuery-Magic */ }

Es folgt ein Handler (.click()), der reagiert, wenn ich auf den Button mit der Klasse ajaxModal klicke.
$('.ajaxModal').click(function () { ... }

In diesem Button gibt es noch das data-Attribut, der wir die id aus der Datenbank mitgeben. Dadurch wissen wir, welchen Eintrag wir in der Datenbank suchen. Mit var lexikonID = $(this).data('id'); speichern wir uns diese id in die Variable lexikonID.

Mit $.ajax({ ... }) haben wir volle Kontrolle über den Ajax Request. Eine genau Beschreibung über diesen asynchronen HTTP request findet ihr auf der offiziellen jQuery Seite
In den geschwungenen Klammer definieren wir zu allererst wohin der Request gehen soll mit url: '/inc/loadModal.inc.php',
Außerdem geben wir den Typ an: type: 'post',. Da wir in dem File inc/loadModal.inc.php die ID für die Datenbankabfrage brauchen, müssen wir hier auch noch die lexikonID mitschicken.
data: { lexikonID: lexikonID },
Ich nenne hier den Parameter, dem ich den Wert meiner lexikonID zuweise gleich, damit ich in weiterer Folge nicht umdenken muss. Ist somit reine Faulheit von mir.
Jetzt ist der Request mit der lexikonID weggeschickt. Im besten Fall, wenn wir die Logik im loadModal.inc.php geschrieben haben, sollte jetzt eine Antwort kommen.
success: function(response) { ... } sagt nichts anderes als, wenn das ganze bisherige Erfolgreich war, nimm den response und mach damit was in der Funktion. In unserem Fall wollen wir den response in das Modal-Gerüst einfügen: $('.modal-content').html(response); und auch anzeigen $('#showModal').modal('show');

Damit endet unser Skript nach einer Menge Klammern die geschlossen werden müssen.

Das inc/loadModal.inc.php

Da wir in diesem File Daten aus der Datenbank lesen brauchen wir am Anfang wieder unsere include-Anweisung für das login.inc.php File. Das File wird in unser Konstrukt des Modals reingeladen, weshalb wir hier auf das übliche HTML Grundgerüst verzichten können.

Durch unser Ajax-Skript (und wenn wir uns nirgends vertippt haben) sollte hier ein $_REQUEST['lexikonID'] ankommen, das wir in eine Variable speichern. In meinem Quellcode heißt die Variable $entryID

Nun können wir das SQL Statement aufbauen und das Ergebnis in eine Variable speichern:
$result = $con->query("SELECT title, imgpath, description FROM content WHERE id = " . $entryID);

In unserem Ajax-Skript haben wir definiert, dass das Ergebnis im response ist. Somit müssen wir hier eine Variable deklarieren mit dem Namen $response
$response = "<div class='modal-header'>";
Achtung: Ihr verwendet hier außen die doppelten Anführungszeichen, somit müsst die die Klassen in einfache Anführungszeichen setzen.

Mit einer while($entry = $result->fetch_assoc()){ ... } können wir wieder jeden einzelnen Eintrag aus unserem Objekt auslesen und unsere Variable $response erweitern (.= ist das Zeichen Werte in einer Variable hinzuzufügen).
$response .= "<h5 class='modal-title'>" . $entry['title'] . "</h5>";
$response .= "<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button>";
$response .= "</div>";

Hier fehlt noch die Div-Box mit dem Bild und der Beschreibung aus der Datenbank.
Wenn unsere Variable $response fertig zusammen gebaut ist folgt nach der while-Schleife noch ein echo $response; und ein exit;
Damit ist das inc/loadModal.inc.php fertig.

Die nächsten Teile:

  1. Login und Registrierung
  2. PHP Live Suche
  3. Einträge editieren und löschen, Bilder verwalten
  4. Kategorie hinzufügen