«Create a folder if it doesn't already exist»: Wie man 2025 das Rad nicht neu erfindet
\n\nHaben Sie jemals ein Skript geschrieben, das Dateien speichern soll, und plötzlich den Fehler Warning: mkdir(): No such file or directory erhalten? Wenn ja, sind Sie nicht allein. Die Frage «Create a folder if it doesn't already exist» hat auf Stack Overflow tausende Aufrufe gesammelt, und das zu Recht. Es scheint so einfach zu sein? Doch in der Praxis stoßen Anfänger (und nicht nur sie) oft auf Fallstricke: Zugriffsrechte, rekursive Erstellung, Race Conditions.
In diesem Artikel behandeln wir die Best Practices für das Erstellen von Ordnern in PHP für das Jahr 2025. Sie erfahren, wie Sie mkdir() richtig verwenden, typische Fehler vermeiden und zuverlässigen Code schreiben, der nicht im ungünstigsten Moment abstürzt. Los geht's!
Warum ist die Frage «Create a folder if it doesn't exist» so beliebt?
\n\nJedes zweite Webprojekt arbeitet irgendwie mit Dateien: Hochladen von Avataren, Generieren von Berichten, Caching, Logging. Und überall muss sichergestellt sein, dass das Zielverzeichnis existiert. Wenn nicht, gibt das Skript einen Fehler aus, der Benutzer sieht einen «500 Internal Server Error», und Sie suchen um drei Uhr morgens nach dem Bug.
\n\nDas Problem ist, dass die PHP-Funktion mkdir() einen Ordner nicht automatisch erstellt, wenn das übergeordnete Verzeichnis fehlt. Viele Entwickler schreiben etwas wie:
if (!file_exists($path)) {\n mkdir($path);\n}\n\n\nUnd das funktioniert … bis eine Race Condition (Wettlaufsituation) auftritt. Wenn zwei Skripte gleichzeitig prüfen, ob ein Ordner existiert, und beide versuchen, ihn zu erstellen, wird eines mit einem Fehler abstürzen. Im Jahr 2025, wenn die Auslastung von Websites steigt, werden solche Bugs kritisch.
\n\nDie Funktion mkdir() in PHP: Eine genaue Analyse
\n\nErinnern wir uns an die Signatur:
\n\nmkdir(string $directory, int $permissions = 0777, bool $recursive = false, resource $context = ?): bool\n\n\n- \n
- $directory — Pfad zum zu erstellenden Ordner. \n
- $permissions — Zugriffsrechte (Standard 0777, aber die umask wird angewendet). \n
- $recursive — Wenn
true, werden alle fehlenden übergeordneten Verzeichnisse erstellt. \n - $context — Stream-Kontext (wird selten verwendet). \n
Das Hauptgeheimnis ist der Parameter $recursive. Die meisten Probleme werden genau damit gelöst. Aber der Reihe nach.
Einfache Methode: is_dir() + mkdir()
\n\nDer offensichtlichste und korrekteste Weg, um zu prüfen, ob ein Ordner existiert, ist die Verwendung von is_dir() anstelle von file_exists(). Warum? Weil file_exists() auch true zurückgibt, wenn eine Datei mit diesem Namen existiert, was zu einem Fehler führt.
$dir = '/path/to/upload';\n\nif (!is_dir($dir)) {\n mkdir($dir, 0755, true);\n}\n\n\nHier:
\n- \n
- Prüfen wir, dass das Verzeichnis nicht existiert und keine Datei ist. \n
- Erstellen wir den Ordner mit den Rechten 0755 (Besitzer darf alles, andere dürfen lesen und ausführen). \n
- Verwenden wir
truefür die rekursive Erstellung – falls der übergeordnete Ordner/path/tonicht existiert, wird auch dieser erstellt. \n
Diese Methode deckt 90% der Fälle ab. Aber was ist, wenn zwei Anfragen gleichzeitig diesen Code ausführen?
\n\nSchutz vor Race Conditions (Wettlaufsituationen)
\n\nIn hochbelasteten Systemen kann es vorkommen, dass zwei Skripte gleichzeitig versuchen, einen Ordner zu erstellen. Um Fehler zu vermeiden, verwenden Sie @ (Fehlerunterdrückung) oder, besser noch, prüfen Sie das Ergebnis von mkdir():
$dir = '/path/to/cache';\n\nif (!is_dir($dir)) {\n // Versuchen zu erstellen. Wenn ein anderer Prozess den Ordner bereits erstellt hat, ist das nicht schlimm\n if (!mkdir($dir, 0755, true) && !is_dir($dir)) {\n throw new \\RuntimeException('Konnte Verzeichnis nicht erstellen: ' . $dir);\n