Es gibt viele Gründe, warum dieser Fehler auftreten kann, und daher hilft eine gute Checkliste, was zuerst überprüft werden muss, erheblich.
Nehmen wir an, wir beheben die folgende Zeile:
require "/path/to/file"
Checkliste
1. Überprüfen Sie den Dateipfad auf Tippfehler
- entweder manuell überprüfen (indem Sie den Pfad visuell überprüfen)
oder verschieben Sie alles, was von require*
oder include*
in eine eigene Variable aufgerufen wird , geben Sie es wieder, kopieren Sie es und versuchen Sie, von einem Terminal aus darauf zuzugreifen:
$path = "/path/to/file";
echo "Path : $path";
require "$path";
Dann in einem Terminal:
cat <file path pasted>
2. Überprüfen Sie, ob der Dateipfad in Bezug auf relative und absolute Pfadüberlegungen korrekt ist
- Wenn es mit einem Schrägstrich "/" beginnt, bezieht es sich nicht auf das Stammverzeichnis des Ordners Ihrer Website (das Dokumentstammverzeichnis), sondern auf das Stammverzeichnis Ihres Servers.
- Das Verzeichnis Ihrer Website könnte beispielsweise sein
/users/tony/htdocs
- Wenn es nicht mit einem Schrägstrich beginnt, stützt es sich entweder auf den Include-Pfad (siehe unten) oder der Pfad ist relativ. Wenn es relativ ist, berechnet PHP relativ zum Pfad des aktuellen Arbeitsverzeichnisses .
- Daher nicht relativ zum Pfad des Stammverzeichnisses Ihrer Website oder zu der Datei, in die Sie eingeben
- Verwenden Sie daher immer absolute Dateipfade
Empfohlene Vorgehensweise :
Um Ihr Skript robust zu machen, falls Sie Dinge verschieben und gleichzeitig zur Laufzeit einen absoluten Pfad generieren, haben Sie zwei Möglichkeiten:
- verwenden
require __DIR__ . "/relative/path/from/current/file"
. Die __DIR__
magische Konstante gibt das Verzeichnis der aktuellen Datei zurück.
Definieren Sie selbst eine SITE_ROOT
Konstante:
- Erstellen Sie im Stammverzeichnis Ihrer Website eine Datei, z
config.php
in config.php
, schreibe
define('SITE_ROOT', __DIR__);
Fügen Sie in jede Datei, in der Sie auf den Site-Stammordner verweisen möchten, config.php
die SITE_ROOT
Konstante ein und verwenden Sie sie, wo immer Sie möchten :
require_once __DIR__."/../config.php";
...
require_once SITE_ROOT."/other/file.php";
Diese beiden Methoden machen Ihre Anwendung auch portabler, da sie nicht auf INI-Einstellungen wie dem Include-Pfad basiert.
3. Überprüfen Sie Ihren Include-Pfad
Eine andere Möglichkeit, Dateien weder relativ noch rein absolut einzuschließen , besteht darin, sich auf den Einschlusspfad zu verlassen . Dies ist häufig bei Bibliotheken oder Frameworks wie dem Zend-Framework der Fall.
Eine solche Aufnahme sieht folgendermaßen aus:
include "Zend/Mail/Protocol/Imap.php"
In diesem Fall sollten Sie sicherstellen, dass der Ordner, in dem sich "Zend" befindet, Teil des Include-Pfads ist.
Sie können den Include-Pfad überprüfen mit:
echo get_include_path();
Sie können einen Ordner hinzufügen mit:
set_include_path(get_include_path().":"."/path/to/new/folder");
4. Überprüfen Sie, ob Ihr Server Zugriff auf diese Datei hat
Es kann sein, dass der Benutzer, der den Serverprozess ausführt (Apache oder PHP), einfach keine Berechtigung zum Lesen oder Schreiben in diese Datei hat.
Um zu überprüfen, unter welchem Benutzer der Server ausgeführt wird, können Sie posix_getpwuid verwenden :
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
Geben Sie den folgenden Befehl in das Terminal ein, um die Berechtigungen für die Datei herauszufinden:
ls -l <path/to/file>
und schauen Sie sich die symbolische Notationsnotation an
5. Überprüfen Sie die PHP-Einstellungen
Wenn keines der oben genannten Verfahren funktioniert hat, besteht das Problem wahrscheinlich darin, dass einige PHP-Einstellungen den Zugriff auf diese Datei untersagen.
Drei Einstellungen könnten relevant sein:
- open_basedir
- Wenn dies eingestellt ist, kann PHP nicht auf Dateien außerhalb des angegebenen Verzeichnisses zugreifen (nicht einmal über einen symbolischen Link).
- Das Standardverhalten ist jedoch, dass es nicht festgelegt wird. In diesem Fall gibt es keine Einschränkung
- Dies kann entweder durch Aufrufen
phpinfo()
oder durch Verwenden überprüft werdenini_get("open_basedir")
- Sie können die Einstellung ändern, indem Sie entweder Ihre php.ini-Datei oder Ihre httpd.conf-Datei bearbeiten
- Sicherheitsmodus
- Wenn dies aktiviert ist, gelten möglicherweise Einschränkungen. Dies wurde jedoch in PHP 5.4 entfernt. Wenn Sie sich noch in einer Version befinden, die ein Upgrade im abgesicherten Modus auf eine PHP-Version unterstützt, die noch unterstützt wird .
- allow_url_fopen und allow_url_include
- Dies gilt nur für das Einschließen oder Öffnen von Dateien über einen Netzwerkprozess wie http: //, nicht für den Versuch, Dateien in das lokale Dateisystem aufzunehmen
- Dies kann mit überprüft
ini_get("allow_url_include")
und eingestellt werdenini_set("allow_url_include", "1")
Eckkoffer
Wenn keine der oben genannten Optionen zur Diagnose des Problems aktiviert ist, können folgende spezielle Situationen auftreten:
1. Die Aufnahme einer Bibliothek unter Verwendung des Einschlusspfads
Es kann vorkommen, dass Sie eine Bibliothek, z. B. das Zend-Framework, über einen relativen oder absoluten Pfad einschließen. Zum Beispiel :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
Aber dann erhalten Sie immer noch die gleiche Art von Fehler.
Dies kann passieren, weil die Datei, die Sie (erfolgreich) aufgenommen haben, selbst eine include-Anweisung für eine andere Datei hat und diese zweite include-Anweisung davon ausgeht, dass Sie den Pfad dieser Bibliothek zum include-Pfad hinzugefügt haben.
Die zuvor erwähnte Zend-Framework-Datei kann beispielsweise Folgendes enthalten:
include "Zend/Mail/Protocol/Exception.php"
Dies ist weder eine Einbeziehung durch den relativen Pfad noch durch den absoluten Pfad. Es wird davon ausgegangen, dass das Zend-Framework-Verzeichnis zum Include-Pfad hinzugefügt wurde.
In einem solchen Fall besteht die einzige praktische Lösung darin, das Verzeichnis zu Ihrem Include-Pfad hinzuzufügen.
2. SELinux
Wenn Sie Security-Enhanced Linux ausführen, kann dies der Grund für das Problem sein, indem Sie den Zugriff auf die Datei vom Server aus verweigern.
Führen Sie den sestatus
Befehl in einem Terminal aus, um zu überprüfen, ob SELinux auf Ihrem System aktiviert ist . Wenn der Befehl nicht vorhanden ist, befindet sich SELinux nicht auf Ihrem System. Wenn es existiert, sollte es Ihnen sagen, ob es erzwungen wird oder nicht.
Um zu überprüfen, ob SELinux-Richtlinien der Grund für das Problem sind, können Sie versuchen, es vorübergehend zu deaktivieren. Seien Sie jedoch VORSICHTIG, da dadurch der Schutz vollständig deaktiviert wird. Tun Sie dies nicht auf Ihrem Produktionsserver.
setenforce 0
Wenn Sie das Problem mit SELinux nicht mehr deaktiviert haben, ist dies die Hauptursache.
Um dies zu lösen , müssen Sie SELinux entsprechend konfigurieren.
Folgende Kontexttypen sind erforderlich:
httpd_sys_content_t
für Dateien, die Ihr Server lesen soll
httpd_sys_rw_content_t
für Dateien, auf die Sie Lese- und Schreibzugriff wünschen
httpd_log_t
für Protokolldateien
httpd_cache_t
für das Cache-Verzeichnis
httpd_sys_content_t
Führen Sie beispielsweise Folgendes aus, um den Kontexttyp Ihrem Website-Stammverzeichnis zuzuweisen :
semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
Wenn sich Ihre Datei in einem Home-Verzeichnis befindet, müssen Sie auch den httpd_enable_homedirs
Booleschen Wert aktivieren:
setsebool -P httpd_enable_homedirs 1
In jedem Fall kann es verschiedene Gründe geben, warum SELinux abhängig von Ihren Richtlinien den Zugriff auf eine Datei verweigert. Sie müssen sich also danach erkundigen. Hier finden Sie ein Tutorial speziell zum Konfigurieren von SELinux für einen Webserver.
3. Symfony
Wenn Sie Symfony verwenden und dieser Fehler beim Hochladen auf einen Server auftritt, wurde der Cache der App möglicherweise nicht zurückgesetzt, entweder weil app/cache
er hochgeladen wurde oder der Cache nicht gelöscht wurde.
Sie können dies testen und beheben, indem Sie den folgenden Konsolenbefehl ausführen:
cache:clear
4. Nicht-ACSII-Zeichen in der Zip-Datei
Anscheinend kann dieser Fehler auch beim Aufrufen auftreten, zip->close()
wenn einige Dateien in der Zip-Datei Nicht-ASCII-Zeichen in ihrem Dateinamen enthalten, z. B. "é".
Eine mögliche Lösung besteht darin, den Dateinamen utf8_decode()
vor dem Erstellen der Zieldatei einzuschließen.
Dank an Fran Cano für die Identifizierung und den Lösungsvorschlag für dieses Problem