Bevor ein Skript in eine Datei schreibt, sollte geprüft werden, ob das überhaupt möglich ist. Fehlt die Schreibberechtigung, gibt PHP eine Warnung aus und der Schreibvorgang schlägt fehl. Die Funktion is_writable() prüft vorab, ob eine Datei oder ein Verzeichnis beschreibbar ist.
Grundlegende Verwendung
Die Funktion erwartet einen Dateipfad und gibt true zurück, wenn die Datei beschreibbar ist, sonst false:
<?php
$datei = '/var/www/html/daten.txt';
if (is_writable($datei)) {
file_put_contents($datei, 'Neue Daten');
echo 'Datei erfolgreich beschrieben.';
} else {
echo 'Datei ist nicht beschreibbar.';
}
?>
Die Prüfung funktioniert sowohl für Dateien als auch für Verzeichnisse. Bei Verzeichnissen wird geprüft, ob neue Dateien darin erstellt werden können.
Praxisbeispiel: Log-Datei schreiben
Ein typischer Einsatz ist das Schreiben in eine Log-Datei. Vor dem Schreibversuch wird geprüft, ob die Datei existiert und beschreibbar ist:
<?php
function logSchreiben(string $nachricht): bool
{
$logDatei = __DIR__ . '/logs/app.log';
$logVerzeichnis = dirname($logDatei);
/* Pruefen ob das Verzeichnis existiert */
if (!is_dir($logVerzeichnis)) {
mkdir($logVerzeichnis, 0755, true);
}
/* Pruefen ob das Verzeichnis beschreibbar ist */
if (!is_writable($logVerzeichnis)) {
error_log('Log-Verzeichnis nicht beschreibbar: '
. $logVerzeichnis);
return false;
}
$zeile = sprintf(
"[%s] %s%s",
date('Y-m-d H:i:s'),
$nachricht,
PHP_EOL
);
return file_put_contents(
$logDatei,
$zeile,
FILE_APPEND | LOCK_EX
) !== false;
}
?>
Die Funktion prüft zuerst das Verzeichnis. Falls es nicht existiert, wird es mit mkdir() angelegt. Erst wenn das Verzeichnis beschreibbar ist, wird die Log-Zeile angehängt. LOCK_EX stellt sicher, dass keine parallelen Schreibvorgänge sich gegenseitig überschreiben.
Verwandte Prüffunktionen
Neben is_writable() gibt es weitere Funktionen, um Dateieigenschaften vor dem Zugriff zu prüfen:
<?php
$datei = 'config.php';
/* Existiert die Datei? */
echo file_exists($datei) ? 'ja' : 'nein';
/* Ist sie lesbar? */
echo is_readable($datei) ? 'ja' : 'nein';
/* Ist sie beschreibbar? */
echo is_writable($datei) ? 'ja' : 'nein';
/* Ist es eine regulaere Datei (kein Verzeichnis)? */
echo is_file($datei) ? 'ja' : 'nein';
?>
In der Praxis wird oft eine Kombination dieser Funktionen verwendet. Zum Beispiel prüft man mit file_exists() ob die Datei vorhanden ist, mit is_readable() ob sie gelesen werden kann, und mit is_writable() ob Schreibzugriff möglich ist.
Hinweis zu clearstatcache()
PHP speichert die Ergebnisse von Dateisystem-Funktionen intern zwischen. Wenn sich die Berechtigungen einer Datei während der Skriptlaufzeit ändern, kann is_writable() trotzdem den alten Wert liefern. In solchen Fällen hilft clearstatcache():
<?php
/* Berechtigungen wurden extern geaendert */
clearstatcache(true, $datei);
/* Jetzt liefert is_writable() den aktuellen Stand */
if (is_writable($datei)) {
echo 'Datei ist jetzt beschreibbar.';
}
?>
Für die meisten Anwendungen ist der Cache kein Problem, da er pro Skriptaufruf neu startet. Nur bei lang laufenden Skripten oder Daemons muss der Cache manuell geleert werden.
Tipp: Berechtigungen richtig setzen
Auf Linux-Servern werden Dateiberechtigungen oft mit chmod gesetzt. Für Webserver-Dateien haben sich folgende Werte bewährt: 0644 für Dateien (Besitzer darf lesen und schreiben, alle anderen nur lesen) und 0755 für Verzeichnisse. Rechte wie 0777 sollten vermieden werden, da sie jedem Benutzer vollen Zugriff gewähren.