Dalam skrip PHP, baik memanggil include()
, require()
, fopen()
, atau turunannya seperti include_once
, require_once
, atau bahkan, move_uploaded_file()
, sering kali kita mengalami kesalahan atau peringatan:
Gagal membuka stream: Tidak ada file atau direktori seperti itu.
Apa proses yang baik untuk menemukan akar penyebab masalah dengan cepat?
Ada banyak alasan mengapa seseorang mungkin mengalami kesalahan ini dan dengan demikian daftar periksa yang baik tentang apa yang harus diperiksa terlebih dahulu sangat membantu. Mari kita pertimbangkan bahwa kita sedang memecahkan masalah pada baris berikut:
require "/path/to/file"
require*
atau include*
ke variabelnya sendiri, echo, salin, dan coba akses dari terminal:
$path = "/path/to/file";
echo "Path : $path";
membutuhkan "$path";
Kemudian, di terminal:
cat <File path yang disisipkan>
/users/tony/htdocs
require __DIR__ . "/relative/path/from/current/file"
. Konstanta ajaib __DIR__
mengembalikan direktori dari file saat ini.SITE_ROOT
:config.php
config.php
, tulis
define('SITE_ROOT', DIR);config.php
, dan kemudian gunakan konstanta SITE_ROOT
di mana pun Anda suka:
require_once DIR."/../config.php";
...
require_once SITE_ROOT."/other/file.php";
Kedua praktik ini juga membuat aplikasi Anda lebih portabel karena tidak bergantung pada pengaturan ini seperti jalur include.
Cara lain untuk menyertakan file, baik secara relatif maupun secara mutlak, adalah dengan mengandalkan include path. Hal ini sering terjadi pada pustaka atau kerangka kerja seperti kerangka kerja Zend. Inklusi seperti itu akan terlihat seperti ini :
include "Zend/Mail/Protocol/Imap.php"
Dalam hal ini, Anda harus memastikan bahwa folder tempat "Zend" berada, adalah bagian dari jalur penyertaan. Anda dapat memeriksa jalur include dengan :
echo get_include_path();
Anda dapat menambahkan folder ke dalamnya dengan :
set_include_path(get_include_path().":"."/path/to/new/folder");
Mungkin saja, pengguna yang menjalankan proses server (Apache atau PHP) tidak memiliki izin untuk membaca atau menulis ke file tersebut. Untuk memeriksa di bawah pengguna apa server berjalan, Anda dapat menggunakan posix_getpwuid :
$user = posix_getpwuid(posix_geteuid());
var_dump($user);
Untuk mengetahui izin pada file, ketik perintah berikut di terminal:
ls -l <path/to/File>
dan lihat [notasi simbolik izin][notasi-izin]
Jika tidak ada satupun cara di atas yang berhasil, maka masalahnya mungkin karena beberapa pengaturan PHP melarangnya untuk mengakses file tersebut. Tiga pengaturan bisa jadi relevan:
phpinfo()
atau dengan menggunakan ini_get("open_basedir")
ini_get("allow_url_include")
dan diatur dengan ini_set("allow_url_include", "1")
Jika tidak ada satupun dari cara di atas yang memungkinkan untuk mendiagnosa masalah, berikut adalah beberapa situasi khusus yang bisa terjadi:
Bisa saja terjadi bahwa Anda menyertakan pustaka, misalnya, kerangka kerja Zend, menggunakan jalur relatif atau absolut. Sebagai contoh :
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
Tetapi kemudian Anda masih mendapatkan jenis kesalahan yang sama. Hal ini bisa terjadi karena file yang telah (berhasil) Anda sertakan, memiliki pernyataan include untuk file lain, dan pernyataan include kedua mengasumsikan bahwa Anda telah menambahkan path dari library tersebut ke path include. Sebagai contoh, berkas Zend framework yang disebutkan sebelumnya dapat memiliki include berikut ini :
include "Zend/Mail/Protocol/Exception.php"
yang bukan merupakan penyertaan dengan jalur relatif, atau dengan jalur absolut. Hal ini dengan asumsi bahwa direktori Zend framework telah ditambahkan ke jalur include.
Dalam kasus seperti itu, satu-satunya solusi praktis adalah menambahkan direktori ke jalur include Anda.
Jika Anda menjalankan Security-Enhanced Linux, maka itu mungkin menjadi alasan untuk masalah ini, dengan menolak akses ke file dari server.
Untuk mengecek apakah SELinux diaktifkan pada sistem Anda, jalankan perintah sestatus
di terminal. Jika perintah tersebut tidak ada, maka SELinux tidak ada pada sistem anda. Jika memang ada, maka perintah tersebut akan memberitahu Anda apakah SELinux diberlakukan atau tidak.
Untuk mengecek apakah kebijakan SELinux adalah alasan untuk masalah tersebut, Anda dapat mencoba mematikannya untuk sementara. Namun berhati-hatilah, karena ini akan menonaktifkan proteksi sepenuhnya. Jangan lakukan ini pada server produksi Anda.
setenforce 0
Jika Anda tidak lagi memiliki masalah dengan SELinux yang dimatikan, maka ini adalah akar penyebabnya. Untuk mengatasinya, Anda harus mengkonfigurasi SELinux yang sesuai. Jenis konteks berikut ini akan diperlukan :
httpd_sys_content_t
untuk file yang Anda ingin server Anda dapat membacanyahttpd_sys_rw_content_t
untuk file-file yang Anda inginkan untuk akses baca dan tulishttpd_log_t
untuk file loghttpd_cache_t
untuk direktori cache
Sebagai contoh, untuk menetapkan tipe konteks httpd_sys_content_t
ke direktori root situs web Anda, jalankan :semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root
Jika file Anda berada di direktori home, Anda juga perlu mengaktifkan boolean httpd_enable_homedirs
:
setsebool -P httpd_enable_homedirs 1
Bagaimanapun, mungkin ada berbagai alasan mengapa SELinux akan menolak akses ke file, tergantung pada kebijakan Anda. Jadi, Anda perlu menanyakan hal itu. Di sini adalah tutorial khusus tentang mengkonfigurasi SELinux untuk server web.
Jika Anda menggunakan Symfony, dan mengalami kesalahan ini saat mengunggah ke server, maka bisa jadi cache aplikasi belum direset, baik karena app/cache
telah diunggah, atau cache belum dihapus.
Anda dapat menguji dan memperbaikinya dengan menjalankan perintah konsol berikut:
cache:clear
Rupanya, kesalahan ini juga dapat terjadi saat memanggil zip->close()
ketika beberapa file di dalam zip memiliki karakter non-ASCII dalam nama filenya, seperti "é".
Solusi potensial adalah membungkus nama file dalam utf8_decode()
sebelum membuat file target.
Kredit untuk Fran Cano yang telah mengidentifikasi dan menyarankan solusi untuk masalah ini
Untuk menambah jawaban (yang sangat bagus) yang sudah ada
open_basedir
adalah salah satu yang dapat membuat Anda bingung karena dapat ditentukan dalam konfigurasi server web. Meskipun hal ini mudah diatasi jika Anda menjalankan server khusus Anda sendiri, ada beberapa paket perangkat lunak hosting bersama di luar sana (seperti Plesk, cPanel, dll) yang akan mengkonfigurasi arahan konfigurasi pada basis per-domain. Karena perangkat lunak membangun berkas konfigurasi (yaitu httpd.conf
), Anda tidak dapat mengubah berkas itu secara langsung karena perangkat lunak hosting akan menimpa berkas itu ketika dimulai ulang.
Dengan Plesk, mereka menyediakan tempat untuk menimpa httpd.conf
yang disediakan yang disebut vhost.conf
. Hanya admin server yang dapat menulis berkas ini. Konfigurasi untuk Apache terlihat seperti ini
<Directory /var/www/vhosts/domain.com>
<IfModule mod_php5.c>
php_admin_flag engine on
php_admin_flag safe_mode off
php_admin_value open_basedir "/var/www/vhosts/domain.com:/tmp:/usr/share/pear:/local/PEAR"
</IfModule>
</Directory>
Mintalah admin server Anda membaca manual untuk hosting dan perangkat lunak server web yang mereka gunakan.
Penting untuk dicatat bahwa mengeksekusi file melalui server web Anda sangat berbeda dengan eksekusi baris perintah atau cron job. Perbedaan besarnya adalah server web Anda memiliki pengguna dan izinnya sendiri. Untuk alasan keamanan, pengguna tersebut sangat dibatasi. Apache, misalnya, sering kali adalah apache
, www-data
atau httpd
(tergantung pada server Anda). Sebuah cron job atau eksekusi CLI memiliki izin apa pun yang dimiliki oleh pengguna yang menjalankannya (misalnya menjalankan skrip PHP sebagai root akan mengeksekusi dengan izin root).
Sering kali orang akan menyelesaikan masalah perizinan dengan melakukan hal berikut (contoh Linux)
chmod 777 /path/to/file
Ini bukan ide yang cerdas, karena berkas atau direktori sekarang dapat ditulis di dunia. Jika Anda memiliki server dan merupakan satu-satunya pengguna maka ini bukan masalah besar, tetapi jika Anda berada di lingkungan shared hosting, Anda baru saja memberikan akses kepada semua orang di server Anda.
Yang perlu Anda lakukan adalah menentukan pengguna yang membutuhkan akses dan hanya memberikan akses kepada mereka. Setelah Anda mengetahui pengguna mana yang memerlukan akses, Anda harus memastikan bahwa
Pengguna tersebut memiliki berkas dan mungkin direktori induk (terutama direktori induk jika Anda ingin menulis berkas). Di sebagian besar lingkungan shared hosting, hal ini tidak akan menjadi masalah, karena pengguna Anda harus memiliki semua berkas di bawah root Anda. Contoh Linux ditunjukkan di bawah ini
chown apache:apache /path/to/file
Pengguna, dan hanya pengguna itu, yang memiliki akses. Di Linux, praktek yang baik adalah chmod 600
(hanya pemilik yang bisa membaca dan menulis) atau chmod 644
(pemilik bisa menulis tetapi semua orang bisa membaca)
Anda dapat membaca diskusi yang lebih panjang tentang perizinan dan pengguna Linux/Unix di sini
Kode saya bekerja dengan baik pada semua mesin-mesin tapi hanya satu ini mulai memberikan masalah (yang digunakan untuk bekerja menemukan saya kira). Digunakan echo "document_root" jalan untuk debug dan juga melihat dekat pada kesalahan, menemukan ini
Peringatan: meliputi(D:/MyProjects/testproject//functions/connections.php): failed to open stream:
Anda dapat dengan mudah melihat di mana masalahnya. Masalah // sebelum fungsi
$document_root = $_SERVER['DOCUMENT_ROOT'];
echo "root: $document_root";
include($document_root.'/functions/connections.php');
Jadi hanya menghapus lading / dari memiliki dan harus bekerja dengan baik. Yang menarik adalah ini perilaku yang berbeda pada versi yang berbeda. Saya menjalankan kode yang sama pada Laptop, Macbook Pro dan PC ini, semua bekerja dengan baik sampai. Semoga ini bisa membantu seseorang.
Itu kasus saya. Itu benar-benar link ke pertanyaan #4485874, tapi saya'm akan menjelaskannya di sini segera.
Ketika anda mencoba untuk meminta path/to/script.php?parameter=value
, PHP mencari file bernama script.php?parameter=value, karena UNIX memungkinkan anda untuk memiliki jalan seperti ini. Jika anda benar-benar perlu untuk melewati beberapa data yang termasuk script, hanya menyatakan hal itu sebagai
$variabel=...atau
$GLOBALS[]=...` atau cara lain yang anda suka.
Samba Saham
Jika anda memiliki Linux server tes dan anda bekerja dari Klien Windows, Samba berbagi mengganggu chmod perintah. Jadi, bahkan jika anda menggunakan:
chmod -R 777 myfolder
di sisi Linux hal ini sepenuhnya mungkin bahwa Kelompok Unix\www-data masih doesn't memiliki akses tulis. Salah satu solusi jika anda berbagi diatur bahwa Windows admin dipetakan ke akar: Dari Jendela, membuka Izin, menonaktifkan Warisan untuk folder anda dengan copy, dan kemudian memberikan akses penuh untuk www-data.
Kemungkinan penyebab lainnya: Mengganti nama dan/atau memindahkan file saat berada di editor teks. Saya melakukan semua langkah di atas tanpa berhasil sampai saya menghapus file yang terus menimbulkan kesalahan ini dan membuat file baru, yang kemudian memperbaiki masalahnya.