Abschnitt 9 · Lektion 3
Ein Paket installieren
Der Befehl dafür heißt composer require, und dahinter steht der Name des Pakets, so wie er auf
Packagist steht, also composer require ramsey/uuid.
In diesem Kurs tippst du ihn nicht selbst. Die Lektionen, die ein Paket brauchen, bringen es schon
mit: Es liegt fertig in der Maschine und wird ausgepackt, bevor dein Code startet, egal ob du auf
Prüfen drückst, die Sandbox startest oder als Erstes etwas ins Terminal tippst. Ins Netz geht
dabei nichts, auch hier nicht. Tippst du composer require trotzdem, antwortet Composer nach einer
knappen Sekunde, es sei offline (you are offline or have misconfigured DNS), und lässt alles, wie
es war: Die Maschine hat keine Verbindung nach draußen, das ist die Regel aus Lektion 1.5. Auf
deinem eigenen Rechner ist es dieser eine Befehl, und der Rest dieser Lektion gilt dort genauso.
Was dabei passiert
Vier Dinge, in dieser Reihenfolge:
- Composer sieht auf Packagist nach, welche Versionen es gibt, und sucht die neueste, die zu deiner Angabe passt. Dabei prüft es auch, ob deine PHP-Version reicht.
- Es lädt das Paket herunter und legt es in
vendor/ab. - Es schreibt den Wunsch in die
composer.jsonund die Tatsache in diecomposer.lock. - Es erzeugt
vendor/autoload.php.
Nur der letzte Punkt betrifft deinen Code, und der ist die halbe Lektion.
Eine Zeile, und der fremde Code ist da
{
"name": "hofladen/kasse",
"require": {
"php": "^8.2",
"ramsey/uuid": "^4"
}
} <?php
// Diese eine Zeile macht jedes installierte Paket benutzbar.
// __DIR__ ist der Ordner, in dem diese Datei liegt.
require __DIR__ . "/vendor/autoload.php";
use Ramsey\Uuid\Uuid;
echo "Erste Kennung: ", Uuid::uuid4(), "\n";
echo "Zweite Kennung: ", Uuid::uuid4(), "\n";
$kennung = Uuid::uuid4();
echo "\nVersion der dritten: ", $kennung->getVersion(), "\n";
echo "Laenge als Text: ", strlen($kennung->toString()), "\n"; require __DIR__ . "/vendor/autoload.php"; steht ganz oben in der Datei, die als erstes läuft, und
zwar genau einmal im ganzen Projekt. Danach kannst du jede Klasse aus jedem installierten Paket
benutzen, ohne eine weitere Zeile.
Was das Auspacken hinterlassen hat, siehst du im Terminal. ls zeigt neben deinen zwei Dateien
einen Ordner vendor und eine composer.lock, die du beide nie angelegt hast. composer show
listet, was installiert ist, je Paket eine Zeile mit Name, Version und Beschreibung. Es sind drei
Zeilen für einen Wunsch, und warum, erklärt Lektion 9.4.
Das ist der Unterschied zwischen Einbinden und Autoloading. ramsey/uuid besteht aus über
hundert Dateien; find vendor/ramsey/uuid -name '*.php' | wc -l zählt sie, 114 sind es. Ohne
Autoloading müsstest du wissen, in welcher davon die Klasse Uuid steht, und sie einzeln einbinden,
und dazu jede Datei, die die wiederum braucht. Mit Autoloading gilt: PHP merkt beim ersten
Uuid::uuid4(), dass es diese Klasse noch nicht kennt, fragt den Autolader, und der weiß, welche
Datei dazugehört. Geladen wird nur, was wirklich benutzt wird.
Das use Ramsey\Uuid\Uuid; darunter lädt übrigens gar nichts. Es ist eine Abkürzung, damit du
unten Uuid::uuid4() schreiben kannst statt Ramsey\Uuid\Uuid::uuid4(). Warum Klassen aus Paketen
so lange Namen haben, steht in Lektion 9.5.
Und wenn die Zeile fehlt
<?php
// Das Paket ist installiert, es liegt in vendor/. Nur weiss PHP
// nichts davon, weil die require-Zeile fehlt.
echo "Diese Zeile laeuft noch.\n";
echo Ramsey\Uuid\Uuid::uuid4(), "\n";
echo "Und hierher kommt das Programm nie.\n"; Genau dieser Fehler passiert jedem einmal, und die Meldung führt in die Irre, wenn man sie nicht
kennt. Auf dem Fehlerkanal steht
PHP Fatal error: Uncaught Error: Class "Ramsey\Uuid\Uuid" not found.
„Class not found” liest sich wie „das Paket ist nicht installiert”. Das Paket ist installiert,
es liegt in vendor/. PHP weiß nur nichts davon, weil niemand den Autolader angemeldet hat.
Sieh dir das Terminal genau an. Die erste Zeile steht in der Ausgabe, der Absturz kommt danach.
Den Exit-Code zeigt dir keine Fläche von selbst; hol das Beispiel im Editor nach vorn und tipp
php index.php; echo $?, dann steht unter der Meldung die 255, wie bei jedem Fatal error seit
Lektion 1.4. Was vor dem Absturz ausgegeben wurde, bleibt stehen, und das hilft beim Suchen: Die
letzte Zeile in der Ausgabe sagt dir, wie weit das Programm gekommen ist. Kommt dir diese Meldung
unter, sieh zuerst nach, ob die require-Zeile oben steht und ob sie auf den richtigen Ordner
zeigt.
Wunsch und Tatsache
{
"name": "hofladen/kasse",
"require": {
"php": "^8.2",
"ramsey/uuid": "^4"
}
} <?php
// Wunsch und Tatsache nebeneinander. Beide Dateien sind JSON, wir
// lesen sie mit den Mitteln aus Lektion 8.3.
$wunsch = json_decode(file_get_contents("composer.json"), true);
$tatsache = json_decode(file_get_contents("composer.lock"), true);
echo "In der composer.json steht der Wunsch:\n";
foreach ($wunsch["require"] as $paket => $bereich) {
echo " ", $paket, " ", $bereich, "\n";
}
echo "\nIn der composer.lock steht, was daraus geworden ist:\n";
foreach ($tatsache["packages"] as $paket) {
echo " ", $paket["name"], " ", $paket["version"], "\n";
} In der composer.json steht ^4. In der composer.lock steht eine Version auf die Ziffer genau.
Das Beispiel legt beides nebeneinander, und der Unterschied ist der ganze Grund, warum es zwei
Dateien gibt. Die Datei selbst ist lang, wc -l composer.lock im Terminal zählt über
zweihundert Zeilen für drei Pakete; head -20 composer.lock zeigt den Anfang, mit der Prüfsumme
über deine composer.json (content-hash) und dem ersten Paket samt der Stelle im Git, aus der es
stammt.
Daraus folgen zwei Befehle, die man leicht verwechselt:
composer installliest diecomposer.lockund stellt genau den Stand her, der dort festgehalten ist. Gibt es keine Lock-Datei, verhält es sich wiecomposer updateund legt eine an.composer updateignoriert die Lock-Datei, fragt Packagist neu, holt die neuesten Versionen im erlaubten Bereich und schreibt die Lock-Datei neu.
Auf einem Server willst du immer composer install. Es liefert denselben Stand, den du getestet
hast, und es fragt niemanden um Erlaubnis. composer update machst du auf deinem eigenen Rechner,
bewusst, und danach lässt du die Tests laufen.
Den Unterschied kannst du hier vorführen, gerade weil die Maschine kein Netz hat. composer install
im Terminal liest die Lock-Datei, sieht, dass alles schon da ist, und meldet Nothing to install, update or remove; eine Zeile dazwischen beschwert sich, dass eine Liste von Packagist nicht zu
holen war, das ist dasselbe fehlende Netz. composer update dagegen scheitert sofort mit derselben
Meldung wie require oben: Es will Packagist fragen, und ohne die Antwort tut es nichts.
Das ist auch die Antwort auf die Frage, warum die Lock-Datei mit in die Versionsverwaltung gehört: Ohne sie hätte jeder Rechner seinen eigenen Stand, und „bei mir läuft es” wäre wieder eine brauchbare Ausrede.
Zum Mitnehmen
Ein Befehl holt das Paket, und eine einzige Zeile in deinem Code macht es benutzbar. Genau diese Zeile ist die, die man am Anfang vergisst, und der Fehler danach sieht aus, als hätte man etwas viel Schlimmeres falsch gemacht.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 3 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.