Istnieje wiele powodów, dla których ktoś może napotkać ten błąd, a zatem dobra lista kontrolna tego, co należy sprawdzić najpierw, znacznie pomaga.
Rozważmy, że rozwiązujemy problem z następującym wierszem:
require "/path/to/file"
Lista kontrolna
1. Sprawdź ścieżkę do pliku pod kątem literówek
- albo sprawdź ręcznie (wizualnie sprawdzając ścieżkę)
lub przenieś cokolwiek jest wywoływane przez require*
lub include*
do jego własnej zmiennej, powtórz to, skopiuj i spróbuj uzyskać do niego dostęp z terminala:
$path = "/path/to/file";
echo "Path : $path";
require "$path";
Następnie w terminalu:
cat <file path pasted>
2. Sprawdź, czy ścieżka do pliku jest poprawna pod względem względów względnych i bezwzględnych
- jeśli zaczyna się od ukośnika „/”, oznacza to, że nie odnosi się do katalogu głównego folderu serwisu WWW (katalogu głównego dokumentu), ale do katalogu głównego serwera.
- na przykład katalogiem Twojej witryny może być
/users/tony/htdocs
- jeśli nie zaczyna się od ukośnika, to albo opiera się na ścieżce dołączania (patrz poniżej), albo ścieżka jest względna. Jeśli jest względna, PHP obliczy względną ścieżkę do bieżącego katalogu roboczego .
- w związku z tym nie względem ścieżki do katalogu głównego Twojej witryny internetowej ani do pliku, w którym piszesz
- z tego powodu zawsze używaj bezwzględnych ścieżek plików
Najlepsze praktyki :
Aby Twój skrypt był niezawodny na wypadek przenoszenia elementów, jednocześnie generując bezwzględną ścieżkę w czasie wykonywania, masz 2 opcje:
- używać
require __DIR__ . "/relative/path/from/current/file"
. __DIR__
Stała magia zwraca katalogu bieżącego pliku.
sam zdefiniuj SITE_ROOT
stałą:
- w katalogu głównym swojej witryny internetowej utwórz plik, np
config.php
w config.php
, napisz
define('SITE_ROOT', __DIR__);
w każdym pliku, do którego chcesz odwołać się do folderu głównego serwisu, dołącz config.php
, a następnie użyj SITE_ROOT
stałej, gdziekolwiek chcesz:
require_once __DIR__."/../config.php";
...
require_once SITE_ROOT."/other/file.php";
Te dwie praktyki sprawiają, że aplikacja jest bardziej przenośna, ponieważ nie opiera się na ustawieniach ini, takich jak ścieżka dołączania.
3. Sprawdź ścieżkę dołączania
Innym sposobem dołączania plików, ani względnym, ani czysto absolutnym, jest poleganie na ścieżce dołączania . Dzieje się tak często w przypadku bibliotek lub frameworków, takich jak framework Zend.
Takie włączenie będzie wyglądać następująco:
include "Zend/Mail/Protocol/Imap.php"
W takim przypadku będziesz chciał się upewnić, że folder, w którym znajduje się „Zend”, jest częścią ścieżki dołączania.
Możesz sprawdzić ścieżkę dołączania za pomocą:
echo get_include_path();
Możesz dodać do niego folder za pomocą:
set_include_path(get_include_path().":"."/path/to/new/folder");
4. Sprawdź, czy serwer ma dostęp do tego pliku
Może się tak zdarzyć, że użytkownik uruchamiający proces serwera (Apache lub PHP) po prostu nie ma uprawnień do odczytu lub zapisu w tym pliku.
Aby sprawdzić, pod jakim użytkownikiem działa serwer, możesz użyć posix_getpwuid :
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
Aby sprawdzić uprawnienia do pliku, wpisz następujące polecenie w terminalu:
ls -l <path/to/file>
i spójrz na symboliczną notację pozwolenia
5. Sprawdź ustawienia PHP
Jeśli żadne z powyższych nie zadziałało, problem prawdopodobnie polega na tym, że niektóre ustawienia PHP zabraniają mu dostępu do tego pliku.
Istotne mogą być trzy ustawienia:
- open_basedir
- Jeśli ta opcja jest ustawiona, PHP nie będzie mieć dostępu do żadnego pliku poza określonym katalogiem (nawet przez dowiązanie symboliczne).
- Jednak domyślne zachowanie nie jest ustawiane, w którym to przypadku nie ma ograniczeń
- Można to sprawdzić, dzwoniąc
phpinfo()
lub używającini_get("open_basedir")
- Możesz zmienić to ustawienie, edytując plik php.ini lub plik httpd.conf
- tryb bezpieczeństwa
- jeśli jest włączona, mogą obowiązywać ograniczenia. Jednak zostało to usunięte w PHP 5.4. Jeśli nadal korzystasz z wersji obsługującej tryb bezpieczny, uaktualnij do wersji PHP, która nadal jest obsługiwana .
- allow_url_fopen i allow_url_include
- dotyczy to tylko dołączania lub otwierania plików za pośrednictwem procesu sieciowego, takiego jak http: //, nie dotyczy próby dołączenia plików do lokalnego systemu plików
- można to sprawdzić
ini_get("allow_url_include")
i ustawić za pomocąini_set("allow_url_include", "1")
Skrzynie narożne
Jeśli żadne z powyższych nie umożliwiło zdiagnozowania problemu, oto kilka specjalnych sytuacji, które mogą się zdarzyć:
1. Włączenie biblioteki korzystającej ze ścieżki dołączania
Może się zdarzyć, że włączysz bibliotekę, na przykład framework Zend, używając ścieżki względnej lub bezwzględnej. Na przykład :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
Ale nadal pojawia się ten sam rodzaj błędu.
Może się tak zdarzyć, ponieważ plik, który został (pomyślnie) dołączony, sam zawiera instrukcję include dla innego pliku, a ta druga instrukcja include zakłada, że dodano ścieżkę tej biblioteki do ścieżki dołączania.
Na przykład wspomniany wcześniej plik frameworka Zend może zawierać następujące elementy:
include "Zend/Mail/Protocol/Exception.php"
co nie jest ani włączeniem przez ścieżkę względną, ani przez ścieżkę absolutną. Zakłada się, że katalog frameworka Zend został dodany do ścieżki włączania.
W takim przypadku jedynym praktycznym rozwiązaniem jest dodanie katalogu do ścieżki dołączania.
2. SELinux
Jeśli używasz systemu Linux z rozszerzonymi zabezpieczeniami, przyczyną problemu może być odmowa dostępu do pliku z serwera.
Aby sprawdzić, czy SELinux jest włączony w twoim systemie, uruchom sestatus
polecenie w terminalu. Jeśli polecenie nie istnieje, oznacza to, że SELinuksa nie ma w twoim systemie. Jeśli istnieje, powinien poinformować Cię, czy jest wymuszony, czy nie.
Aby sprawdzić, czy przyczyną problemu są polityki SELinux , możesz spróbować tymczasowo je wyłączyć. Należy jednak uważać, ponieważ spowoduje to całkowite wyłączenie ochrony. Nie rób tego na serwerze produkcyjnym.
setenforce 0
Jeśli nie masz już problemu z wyłączonym SELinuksem, to jest to główna przyczyna.
Aby go rozwiązać , będziesz musiał odpowiednio skonfigurować SELinux.
Niezbędne będą następujące typy kontekstów:
httpd_sys_content_t
dla plików, które serwer ma mieć możliwość odczytu
httpd_sys_rw_content_t
dla plików, dla których chcesz mieć dostęp do odczytu i zapisu
httpd_log_t
dla plików dziennika
httpd_cache_t
dla katalogu pamięci podręcznej
Na przykład, aby przypisać httpd_sys_content_t
typ kontekstu do katalogu głównego serwisu WWW, uruchom:
semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
Jeśli twój plik znajduje się w katalogu domowym, musisz również włączyć wartość httpd_enable_homedirs
logiczną:
setsebool -P httpd_enable_homedirs 1
W każdym razie może istnieć wiele powodów, dla których SELinux mógłby odmówić dostępu do pliku, w zależności od polityki użytkownika. Więc będziesz musiał się o to dowiedzieć. Oto samouczek dotyczący konfigurowania SELinux dla serwera WWW.
3. Symfony
Jeśli używasz Symfony i napotykasz ten błąd podczas przesyłania na serwer, może to być spowodowane tym, że pamięć podręczna aplikacji nie została zresetowana, ponieważ app/cache
została załadowana lub pamięć podręczna nie została wyczyszczona.
Możesz to przetestować i naprawić, uruchamiając następujące polecenie konsoli:
cache:clear
4. Znaki inne niż ACSII w pliku ZIP
Najwyraźniej ten błąd może wystąpić również podczas wywoływania, zip->close()
gdy niektóre pliki w pliku zip mają w nazwie znaki inne niż ASCII, takie jak „é”.
Potencjalnym rozwiązaniem jest zawinięcie nazwy pliku utf8_decode()
przed utworzeniem pliku docelowego.
Podziękowania dla Fran Cano za zidentyfikowanie i zasugerowanie rozwiązania tego problemu