Apakah PHP menyertakan jalur relatif terhadap file atau kode panggilan?

111

Saya mengalami masalah dalam memahami kumpulan aturan tentang jalur include relatif PHP. Jika saya menjalankan file A.PHP- dan file A.PHP menyertakan file B.PHP yang menyertakan file C.PHP, sebaiknya jalur relatif ke C.PHP terkait dengan lokasi B.PHP, atau ke lokasi A .PHP? Artinya, apakah penting dari file mana include dipanggil, atau hanya apa direktori kerja saat ini- dan apa yang menentukan direktori kerja saat ini?

Yarin
sumber
Lebih akurat daripada jawaban yang diterima menurut saya: stackoverflow.com/a/23902890/1636522 .
daun

Jawaban:

132

Ini relatif terhadap skrip utama, dalam hal ini A.php. Ingatlah bahwa include()hanya memasukkan kode ke dalam skrip yang sedang berjalan.

Artinya, apakah penting dari file mana penyertaan tersebut dipanggil

Tidak.

Jika Anda ingin membuatnya penting, dan melakukan include terhadap B.php, gunakan __FILE__konstanta (atau __DIR__sejak PHP 5.2 IIRC) yang akan selalu mengarah ke file literal saat ini tempat baris kodenya berada.

include(dirname(__FILE__)."/C.PHP");
Pekka
sumber
@ Pekka- mengagumkan- persis apa yang saya cari. Untuk info lebih lanjut, lihat stackoverflow.com/questions/2184810/…
Yarin
7
Anda juga dapat menggunakannya __DIR__untuk tujuan yang tepat.
Nick Bedford
1
Jawaban ini agak berlebihan: TIDAK PERLU include(dirname(__FILE__)."/C.PHP");, karena include("C.PHP");sudah cukup (Ya! C.PHP dapat berada di direktori yang sama dengan B.PHP) Ini mungkin gagal hanya jika ada dua file C.PHP dalam proyek Anda.
Johnny Wong
Untuk membuatnya lebih jelas: Ini relatif terhadap B.php dan A.php jika tanpa awalan "./" atau "../" di jalur penyertaan. Lihat jawaban saya di bawah.
Johnny Wong
21

@Pekka membawa saya ke sana, tetapi hanya ingin membagikan apa yang saya pelajari:

getcwd() mengembalikan direktori tempat file yang Anda mulai jalankan berada.

dirname(__FILE__) mengembalikan direktori file yang berisi kode yang sedang dijalankan.

Dengan menggunakan dua fungsi ini, Anda selalu dapat membuat jalur penyertaan yang sesuai dengan yang Anda butuhkan.

Misalnya, jika b.php dan c.php berbagi direktori, b.php dapat menyertakan c.php seperti:

include(dirname(__FILE__).'/c.php');

tidak peduli dari mana b.php dipanggil.

Faktanya, ini adalah cara yang lebih disukai untuk membuat jalur relatif, karena kode tambahan membebaskan PHP dari keharusan melakukan iterasi melalui include_path dalam upaya untuk menemukan file target.

Sumber:

Perbedaan Antara getcwd () dan dirname (__ FILE__)? Yang mana yang harus saya gunakan?

Mengapa Anda harus menggunakan dirname (__ FILE__)

Yarin
sumber
Saya ingin menambahkan sesuatu, saya memiliki file bernama csb.php, termasuk file fungsi dari folder, dan file fungsi menyertakan file bernama t.php dari folder yang sama dengan file fungsi, Ketika saya mencoba memasukkan file bernama csb.php dari folder t.php, itu mulai termasuk csb.php yang sama yang memanggil file fungsi, tetapi ketika saya mengubah csb.php kedua menjadi csbe.php itu mulai langsung bekerja. Jadi, sepertinya itu memprioritaskan folder pertama, lalu folder include kedua!
Miguel Vieira
18
  1. Jika termasuk jalur tidak dimulai dengan ./atau ../, misalnya:

    include 'C.php'; // precedence: include_path (which include '.' at first),
                     // then path of current `.php` file (i.e. `B.php`), then `.`.
  2. Jika menyertakan jalur dimulai dengan ./atau ../, misalnya:

    include './C.php';  // relative to '.'
    
    include '../C.php'; // also relative to '.'

The .atau ..di atas adalah relatif terhadap getcwd(), yang default ke jalan masuknya .phpberkas (yaitu A.php).

Diuji pada PHP 5.4.3 (Tanggal Pembuatan: 8 Mei 2012 00:47:34).

(Perhatikan juga bahwa chdir()dapat mengubah output getcwd().)

Johnny Wong
sumber
Untuk menyimpulkan, jalur A.php pertama-tama mencari C.php, kemudian jalur B.php dicari jika tidak ada prefiks './' atau '../' di sertakan. (Asumsikan pengaturan default PHP)
Johnny Wong
Terima kasih telah memberi petunjuk kepada saya untuk menggunakan chdir(__DIR__)untuk memperbaiki masalah.
HartleySan
[...] getcwd(), yang defaultnya ke jalur entri file .php [...] - belum tentu benar. Jika saya menjalankan PHP pada baris perintah maka getcwd()mengacu pada direktori kerja saat ini dari shell, apa pun .phpfile yang saya panggil. Saya dapat membayangkan, meskipun, bahwa jika PHP dijalankan di lingkungan server web, lingkungan menginisialisasi direktori kerja saat ini ke .phpfile entri . Diuji di macOS dengan PHP 7.2.2 yang diinstal melalui Homebrew.
herzbube
17

Jawaban Pekka yang diterima tidak lengkap dan, dalam konteks umum, menyesatkan. Jika file disediakan sebagai jalur relatif, konstruksi bahasa yang dipanggil includeakan mencarinya dengan cara berikut.

Pertama, ini akan melalui jalur variabel lingkungan include_path, yang dapat disetel dengan ini_set. Jika gagal, ia akan mencari di direktori skrip pemanggil itu sendiri dirname(__FILE__)( __DIR__dengan php> = 5.3.) Jika ini juga gagal, barulah ia akan mencari di direktori kerja! Ternyata, secara default, variabel lingkungan include_pathdimulai dengan ., yang merupakan direktori kerja saat ini. Itulah satu-satunya alasan mengapa ia mencari pertama kali di direktori kerja saat ini. Lihat http://php.net/manual/en/function.include.php .

File disertakan berdasarkan jalur file yang diberikan atau, jika tidak ada yang diberikan, include_path ditentukan. Jika file tidak ditemukan di include_path, include akhirnya akan memeriksa direktori skrip pemanggil itu sendiri dan direktori kerja saat ini sebelum gagal.

Jadi, jawaban yang benar untuk bagian pertama dari pertanyaan ini adalah bahwa penting di mana berada skrip panggilan yang disertakan. Jawaban untuk bagian terakhir dari pertanyaan ini adalah bahwa direktori kerja awal , dalam konteks server web, adalah direktori dari skrip yang disebut, skrip yang mencakup semua yang lain saat ditangani oleh PHP. Dalam konteks baris perintah, direktori kerja awal adalah apa pun itu ketika php dipanggil pada prompt, tidak harus direktori tempat skrip yang dipanggil berada. The saat direktori kerja, bagaimanapun, dapat diubah pada waktu berjalan dengan fungsi PHP chdir. Lihat http://php.net/manual/en/function.chdir.php .

Paragraf ini ditambahkan untuk mengomentari jawaban lain. Beberapa telah menyebutkan bahwa mengandalkan include_pathkurang kuat dan oleh karena itu lebih disukai menggunakan jalur lengkap seperti ./pathatau __DIR__ . /path. Beberapa orang bahkan mengatakan bahwa mengandalkan direktori kerja .itu sendiri tidak aman, karena dapat diubah. Namun, terkadang, Anda perlu mengandalkan nilai lingkungan. Misalnya, Anda mungkin ingin include_pathmengosongkan, sehingga direktori skrip pemanggil adalah tempat pertama yang akan dicari, bahkan sebelum direktori kerja saat ini. Kode mungkin sudah ditulis dan diperbarui secara teratur dari sumber eksternal dan Anda tidak ingin memasukkan kembali awalan __DIR__setiap kali kode diperbarui.


sumber
"jika gagal, ini akan mencari di direktori skrip pemanggil sendiri dirname(__FILE__) (__DIR__)dengan php> = 5.3.)" Anda yakin? Dimana didokumentasikan? Saya harap Anda salah, dan PHP tidak menggunakan __FILE__dan __DIR__untuk tujuan ini , karena hal itu akan segera merusak termasuk skrip "sibling" dari yang terhubung dengan symlink ! : -o (Untungnya, tampaknya berfungsi dengan baik di sini, di pengaturan 7.1 saya.)
Sz.
6

Jawaban singkat: ini relatif terhadap skrip penyertaan.

TFM menjelaskannya dengan benar:

Jika file tidak ditemukan di include_path, include akan diperiksa di direktori skrip pemanggil dan direktori kerja saat ini

Jadi, jika /app/main.php mengatakan include("./inc.php")itu akan menemukan /app/inc.php .

Itu ./ tidak benar-benar diperlukan, tetapi menghilangkan ketergantungan apapun pada include_path.

Saya tidak akan mengandalkan menemukan file yang disertakan dalam direktori kerja saat ini jika seseorang mengubahnya dengan chdir().

Denis Howe
sumber
Jadi jika Anda memulai string dengan ./, apakah itu memeriksa direktori skrip pemanggil terlebih dahulu atau direktori kerja saat ini terlebih dahulu?
Pacerier
2
@Denis Howe Tidak, Anda sudah bergantung pada direktori kerja saat ini jika jalur include Anda dimulai dengan ./. yaitu chdir ("/ app / other") akan membuat include("./inc.php")gagal. Jadi, gunakan include("inc.php")untuk aman dalam kasus ini.
Johnny Wong
@Pacerier jika string dimulai dengan ./ atau ../, ini hanya memeriksa direktori kerja saat ini. (include_path dan direktori skrip pemanggil (B.php) keduanya diabaikan). Lihat jawaban saya untuk lebih jelasnya.
Johnny Wong
-2
dir
-> a.php
-> c.php

- dir2 
-> b.php

Untuk menyertakan adalam bAnda perluinclude("../a.php");

Untuk menyertakan bdalam cAnda perluinclude("dir2/b.php");

Olli
sumber
4
@ Olli- Anda kehilangan inti dari pertanyaannya- Saya bertanya tentang bagaimana jalur relatif ditentukan ketika penyertaan dirantai.
Yarin