PHP - Gagal membuka stream: Tidak ada file atau direktori seperti itu

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?

Mengomentari pertanyaan (3)
Larutan

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"


Daftar Periksa


1. Periksa jalur berkas dari kesalahan ketik

  • baik memeriksa secara manual (dengan memeriksa jalur secara visual)
  • atau pindahkan apapun yang dipanggil oleh 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>

    2. Periksa apakah jalur file sudah benar terkait pertimbangan jalur relatif vs absolut

  • jika dimulai dengan garis miring ke depan "/" maka itu tidak mengacu pada root folder situs web Anda (root dokumen), tetapi ke root server Anda.
    • sebagai contoh, direktori situs web Anda mungkin /users/tony/htdocs
  • jika tidak diawali dengan garis miring ke depan maka itu berarti mengandalkan jalur include (lihat di bawah) atau jalurnya relatif. Jika relatif, maka PHP akan menghitung secara relatif ke path dari current working directory.
    • Dengan demikian, tidak relatif terhadap path dari root situs web Anda, atau terhadap file di mana Anda mengetikkan
    • untuk alasan itu, selalu gunakan jalur berkas absolut Praktik terbaik: Untuk membuat skrip Anda kuat jika Anda memindahkan sesuatu, sementara masih menghasilkan jalur absolut pada saat runtime, Anda memiliki 2 opsi:
  1. Gunakan require __DIR__ . "/relative/path/from/current/file". Konstanta ajaib __DIR__ mengembalikan direktori dari file saat ini.
  2. Definisikan sendiri konstanta SITE_ROOT :
    • pada root direktori situs web Anda, buatlah sebuah file, misalnya config.php
    • dalam config.php, tulis define('SITE_ROOT', DIR);
    • di setiap file di mana Anda ingin mereferensikan folder root situs, sertakan 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.

      3. Periksa jalur include Anda

      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");


4. Periksa apakah server Anda memiliki akses ke file tersebut

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]

5. Periksa pengaturan PHP

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:

  1. open_basedir
  • Jika ini diatur, PHP tidak akan dapat mengakses file apapun di luar direktori yang ditentukan (bahkan tidak melalui link simbolik).
  • Namun, perilaku defaultnya adalah untuk tidak disetel dalam hal ini tidak ada pembatasan
  • Hal ini dapat diperiksa dengan memanggil phpinfo() atau dengan menggunakan ini_get("open_basedir")
  • Anda dapat mengubah pengaturan baik dengan mengedit file php.ini atau file httpd.conf Anda
  1. safe mode
  • jika ini diaktifkan pembatasan mungkin berlaku. Namun, ini telah dihapus di PHP 5.4. Jika Anda masih menggunakan versi yang mendukung safe mode, upgrade ke versi PHP yang masih didukung.
  1. allow_url_fopen dan allow_url_include
  • ini hanya berlaku untuk menyertakan atau membuka file melalui proses jaringan seperti http:// bukan ketika mencoba menyertakan file pada sistem file lokal
  • ini dapat diperiksa dengan ini_get("allow_url_include") dan diatur dengan ini_set("allow_url_include", "1")

    Kasus sudut

    Jika tidak ada satupun dari cara di atas yang memungkinkan untuk mendiagnosa masalah, berikut adalah beberapa situasi khusus yang bisa terjadi:

    1. Penyertaan pustaka yang bergantung pada jalur include

    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.

2. SELinux

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 membacanya
  • httpd_sys_rw_content_t untuk file-file yang Anda inginkan untuk akses baca dan tulis
  • httpd_log_t untuk file log
  • httpd_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.

3. Symfony

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


4. Karakter non ACSII di dalam file Zip

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

Komentar (7)

Untuk menambah jawaban (yang sangat bagus) yang sudah ada

Perangkat Lunak Hosting Bersama

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



        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"

Mintalah admin server Anda membaca manual untuk hosting dan perangkat lunak server web yang mereka gunakan.

Izin File

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

  1. 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
  2. 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

Komentar (0)
  1. Lihat di tepat kesalahan

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.

  1. Copy lalu lokasi file di browser untuk memastikan file yang ada. Kadang-kadang file yang bisa dihapus secara tiba-tiba (terjadi dengan saya) dan itu juga masalah dalam kasus saya.
Komentar (2)

Tambahkan skrip dengan query parameter

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.

Komentar (0)

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.

Komentar (0)

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.

Komentar (3)