mitmario.dev

Ein Paket installieren

PHP Sandbox 4 Min Lesezeit 3 BeispieleLektion 3 von 6

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:

  1. 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.
  2. Es lädt das Paket herunter und legt es in vendor/ ab.
  3. Es schreibt den Wunsch in die composer.json und die Tatsache in die composer.lock.
  4. 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

Die eine Zeile, die alles einbindet
<?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

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

Was in composer.lock steht
<?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 install liest die composer.lock und stellt genau den Stand her, der dort festgehalten ist. Gibt es keine Lock-Datei, verhält es sich wie composer update und legt eine an.
  • composer update ignoriert 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, kostenlos

Zu 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.