PHP có bao gồm các đường dẫn liên quan đến tệp hoặc mã gọi không?


110

Tôi đang gặp khó khăn khi hiểu bộ quy tắc liên quan đến các đường dẫn bao gồm tương đối trong PHP. Nếu tôi chạy tệp A.PHP- và tệp A.PHP bao gồm tệp B.PHP bao gồm tệp C.PHP, thì đường dẫn liên quan đến C.PHP phải liên quan đến vị trí của B.PHP hoặc vị trí của A .PHP? Đó là, không quan trọng tệp bao gồm được gọi từ hay chỉ thư mục làm việc hiện tại là gì- và điều gì quyết định thư mục làm việc hiện tại?


Theo ý kiến ​​của tôi, chính xác hơn câu trả lời được chấp nhận: stackoverflow.com/a/23902890/1636522 .
leaf

Câu trả lời:


132

Nó liên quan đến kịch bản chính, trong trường hợp này là A.php. Hãy nhớ rằng include()chỉ cần chèn mã vào tập lệnh hiện đang chạy.

Đó là, không quan trọng tệp bao gồm được gọi từ

Không.

Nếu bạn muốn làm cho nó quan trọng và thực hiện bao gồm liên quan đến B.php, hãy sử dụng __FILE__hằng số (hoặc __DIR__kể từ PHP 5.2 IIRC), hằng số này sẽ luôn trỏ đến tệp hiện tại theo nghĩa đen mà dòng mã nằm trong đó.

include(dirname(__FILE__)."/C.PHP");

@ Pekka- tuyệt vời- đúng là thứ tôi đang tìm kiếm. Để biết thêm thông tin, hãy xem stackoverflow.com/questions/2184810/…
Yarin

7
Bạn cũng có thể sử dụng __DIR__cho mục đích chính xác đó.
Nick Bedford

1
Câu trả lời này hơi quá mức cần thiết: KHÔNG CẦN include(dirname(__FILE__)."/C.PHP");, vì include("C.PHP");là đủ (Có! C.PHP có thể nằm trong cùng thư mục với B.PHP) Nó chỉ có thể thất bại khi có hai tệp C.PHP trong dự án của bạn.
Johnny Wong

Để làm rõ hơn: Nó tương đối với cả B.php và A.php nếu không có tiền tố "./" hoặc "../" trong đường dẫn bao gồm. Xem câu trả lời của tôi dưới đây.
Johnny Wong

21

@Pekka đưa tôi đến đó, nhưng chỉ muốn chia sẻ những gì tôi học được:

getcwd() trả về thư mục chứa tệp bạn bắt đầu thực thi.

dirname(__FILE__) trả về thư mục của tệp chứa mã hiện đang thực thi.

Sử dụng hai hàm này, bạn luôn có thể tạo một đường dẫn bao gồm liên quan đến những gì bạn cần.

Ví dụ: nếu b.php và c.php chia sẻ một thư mục, b.php có thể bao gồm c.php như:

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

bất kể b.php được gọi từ đâu.

Trên thực tế, đây là cách ưa thích để thiết lập các đường dẫn tương đối, vì mã bổ sung giải phóng PHP khỏi việc phải lặp lại qua include_path trong nỗ lực định vị tệp đích.

Nguồn:

Sự khác biệt giữa getcwd () và dirname (__ FILE__)? Tôi nên sử dụng cái nào?

Tại sao bạn nên sử dụng dirname (__ FILE__)


Tôi muốn thêm thứ gì đó, tôi đã có một tệp có tên csb.php, bao gồm một tệp chức năng từ một thư mục và tệp chức năng bao gồm một tệp có tên t.php từ cùng một thư mục với tệp chức năng, Khi tôi thử đưa vào tệp có tên csb.php từ thư mục t.php, nó bắt đầu bao gồm cùng một tệp csb.php được gọi là tệp chức năng, nhưng khi tôi thay đổi csb.php thứ hai thành csbe.php, nó bắt đầu hoạt động ngay lập tức. Vì vậy, có vẻ như nó ưu tiên thư mục đầu tiên, sau đó đến thư mục bao gồm thứ hai!
Miguel Vieira

17
  1. Nếu đường dẫn bao gồm không bắt đầu bằng ./hoặc ../, ví dụ:

    include 'C.php'; // precedence: include_path (which include '.' at first),
                     // then path of current `.php` file (i.e. `B.php`), then `.`.
    
  2. Nếu đường dẫn bao gồm bắt đầu bằng ./hoặc ../, ví dụ:

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

Các .hoặc ..ở trên là tương đối so với getcwd(), mặc định là con đường của sự xâm nhập .phptập tin (ví dụ A.php).

Đã thử nghiệm trên PHP 5.4.3 (Ngày xây dựng: 8 tháng 5 năm 2012 00:47:34).

(Cũng lưu ý rằng chdir()có thể thay đổi đầu ra của getcwd().)


Để kết luận, đường dẫn của A.php trước tiên được tìm kiếm cho C.php, sau đó đường dẫn của B.php được tìm kiếm nếu không có tiền tố './' hoặc '../' trong bao gồm. (Giả sử cài đặt mặc định của PHP)
Johnny Wong

Cảm ơn vì đã giúp tôi sử dụng chdir(__DIR__)để khắc phục sự cố.
HartleySan

[...] getcwd(), mặc định là đường dẫn của tệp .php mục nhập [...] - không nhất thiết phải đúng. Nếu tôi chạy PHP trên dòng lệnh thì getcwd()tham chiếu đến thư mục làm việc hiện tại của shell, bất kể .phptôi gọi tệp nào. Tuy nhiên, tôi có thể tưởng tượng rằng nếu PHP được chạy trong môi trường máy chủ web mà môi trường đó khởi tạo thư mục làm việc hiện tại cho .phptệp mục nhập . Đã thử nghiệm trên macOS với PHP 7.2.2 được cài đặt qua Homebrew.
herzbube

16

Câu trả lời được chấp nhận của Pekka là không đầy đủ và, trong bối cảnh chung, gây hiểu lầm. Nếu tệp được cung cấp dưới dạng một đường dẫn tương đối, cấu trúc ngôn ngữ được gọi includesẽ tìm kiếm tệp đó theo cách sau.

Đầu tiên, nó sẽ đi qua các đường dẫn của biến môi trường include_path, có thể được thiết lập với ini_set. Nếu không thành công, nó sẽ tìm kiếm trong thư mục riêng của tập lệnh gọi dirname(__FILE__)( __DIR__với php> = 5.3.) Nếu điều này cũng không thành công, chỉ khi đó nó sẽ tìm kiếm trong thư mục làm việc! Nó chỉ ra rằng, theo mặc định, biến môi trường include_pathbắt đầu bằng ., là thư mục làm việc hiện tại. Đó là lý do duy nhất khiến nó tìm kiếm đầu tiên trong thư mục làm việc hiện tại. Xem http://php.net/manual/en/ Chức năng.include.php .

Các tệp được bao gồm dựa trên đường dẫn tệp đã cho hoặc nếu không có đường dẫn nào được chỉ định, thì include_path được chỉ định. Nếu tệp không được tìm thấy trong include_path, thì cuối cùng, include sẽ kiểm tra trong thư mục riêng của tập lệnh gọi và thư mục làm việc hiện tại trước khi bị lỗi.

Vì vậy, câu trả lời chính xác cho phần đầu tiên của câu hỏi là nó nằm ở đâu tập lệnh gọi bao gồm. Câu trả lời cho phần cuối cùng của câu hỏi là thư mục làm việc ban đầu , trong ngữ cảnh máy chủ web, là thư mục của tập lệnh được gọi, tập lệnh bao gồm tất cả các thư mục khác trong khi được PHP xử lý. Trong ngữ cảnh dòng lệnh, thư mục làm việc ban đầu là bất kỳ thứ gì khi php được gọi tại dấu nhắc, không nhất thiết là thư mục chứa tập lệnh được gọi. Các hiện thư mục làm việc, tuy nhiên, có thể thay đổi thời gian chạy với chức năng PHP chdir. Xem http://php.net/manual/en/ Chức năng.chdir.php .

Đoạn này được thêm vào để bình luận về các câu trả lời khác. Một số người đã đề cập rằng việc dựa vào include_pathlà kém mạnh mẽ hơn và do đó tốt hơn là sử dụng các đường dẫn đầy đủ như ./pathhoặc __DIR__ . /path. Một số còn nói rằng dựa vào .chính thư mục làm việc là không an toàn, vì nó có thể bị thay đổi. Tuy nhiên, đôi khi, bạn cần dựa vào các giá trị môi trường. Ví dụ: bạn có thể muốn đặt include_pathtrống, để thư mục của tập lệnh gọi là nơi đầu tiên mà nó sẽ tìm kiếm, ngay cả trước thư mục làm việc hiện tại. Mã có thể đã được viết và cập nhật thường xuyên từ các nguồn bên ngoài và bạn không muốn chèn lại tiền tố __DIR__mỗi khi mã được cập nhật.


"nếu điều này không thành công, nó sẽ tìm kiếm trong thư mục riêng của tập lệnh gọi dirname(__FILE__) (__DIR__)với php> = 5.3.)" Bạn có chắc không? Nó được ghi lại ở đâu? Tôi hy vọng bạn là sai, và PHP không không sử dụng __FILE____DIR__cho này mục đích, vì điều đó sẽ nhanh chóng phá vỡ bao gồm "anh chị em" kịch bản từ symlinked người! : -o (May mắn thay, có vẻ như hoạt động tốt ở đây, trên thiết lập 7.1 của tôi.)
Sz.

6

Câu trả lời ngắn gọn: nó liên quan đến script bao gồm.

TFM giải thích nó một cách chính xác:

Nếu tệp không được tìm thấy trong include_path, thì include sẽ kiểm tra trong thư mục của tập lệnh gọi và thư mục làm việc hiện tại

Vì vậy, nếu /app/main.php nói include("./inc.php")rằng điều đó sẽ tìm thấy /app/inc.php .

Các ./ là không thực sự cần thiết nhưng loại bỏ bất kỳ sự phụ thuộc vào include_path.

Tôi sẽ không dựa vào việc tìm kiếm các tệp bao gồm trong thư mục làm việc hiện tại trong trường hợp ai đó thay đổi nó bằng chdir().


Vì vậy, nếu bạn bắt đầu chuỗi bằng ./, nó sẽ kiểm tra thư mục của tập lệnh gọi trước hay thư mục làm việc hiện tại trước?
Pacerier

2
@Denis Howe Không, bạn đã phụ thuộc vào thư mục làm việc hiện tại nếu đường dẫn bao gồm của bạn bắt đầu bằng ./. tức là chdir ("/ app / other") sẽ include("./inc.php")không thành công. Vì vậy, sử dụng include("inc.php")để được an toàn trong trường hợp này.
Johnny Wong

@Pacerier nếu chuỗi bắt đầu bằng ./ hoặc ../, nó chỉ kiểm tra thư mục làm việc hiện tại. (include_path và thư mục gọi script (B.php) đều bị bỏ qua). Xem câu trả lời của tôi để biết thêm chi tiết.
Johnny Wong

-2
dir
-> a.php
-> c.php

- dir2 
-> b.php

Để đưa avào bbạn cần phảiinclude("../a.php");

Để đưa bvào cbạn cần phảiinclude("dir2/b.php");


4
@ Olli- bạn đang thiếu điểm của câu hỏi- Tôi đang hỏi về cách xác định các đường dẫn tương đối khi bao gồm được xâu chuỗi.
Yarin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.