Menu

include và require trong PHP: nạp file PHP khác

include 'header.php'; chạy một file PHP khác ngay tại vị trí đó, như thể code của nó được dán vào. require làm điều tương tự nhưng dừng script với lỗi nghiêm trọng (fatal error) khi không tìm thấy file, còn include chỉ cảnh báo rồi chạy tiếp. include_once và require_once chỉ nạp file ở lần đầu tiên.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

include 'header.php'; chạy code của một file PHP khác tại đúng vị trí đó trong script, như thể nó được dán vào. require 'header.php'; làm điều tương tự, nhưng nếu không nạp được file thì require dừng script với lỗi nghiêm trọng, còn include chỉ in ra cảnh báo rồi chạy tiếp. Cách dùng đầu tiên thường gặp là phần header và footer dùng chung cho mọi trang.

Khối code này ghi header.php và footer.php trước, để có file mà include. Chạy nó rồi xem tab Trang:

Các file được include là file PHP bình thường: chúng có thể chứa HTML với thẻ <?= ?>, và thấy được biến $title được gán trước lệnh require. Đổi tiêu đề rồi chạy lại; mọi trang require header đều nhận thay đổi khi bạn sửa đúng một file đó.

include và require

Khác biệt duy nhất là chuyện gì xảy ra khi file bị thiếu hoặc không đọc được. include in ra hai cảnh báo, cho giá trị false, và script chạy tiếp:

Warning: include(sidebar.php): Failed to open stream: No such file or directory in /home/index.php on line 2

Warning: include(): Failed opening 'sidebar.php' for inclusion (include_path='.:/usr/share/php83') in /home/index.php on line 2

require in ra cùng cảnh báo đó rồi ném ra một Error, khiến script kết thúc trừ khi có code bắt lỗi:

PHP Warning:  require(config.php): Failed to open stream: No such file or directory in /home/index.php on line 2
PHP Fatal error:  Uncaught Error: Failed opening required 'config.php' (include_path='.:/usr/share/php83') in /home/index.php:2

Vì vậy, hãy dùng require cho những gì trang không thể chạy thiếu (cấu hình, thư viện hàm, file lớp) và include cho các phần tùy chọn. Với phần có thể vắng mặt một cách hợp lệ, hãy kiểm tra trước thay vì dựa vào cảnh báo:

Đầu ra:

Spring sale: 20% off
banner.php included, include returned int(1)
sidebar.php not found, skipped

include_once và require_once

File định nghĩa một hàm hay một lớp chỉ được nạp một lần: nạp lần thứ hai là lỗi nghiêm trọng, vì hàm đã tồn tại.

Fatal error: Cannot redeclare greet() (previously declared in /home/helpers.php:2) in /home/helpers.php on line 2

Điều này xảy ra ngay khi hai file cùng require 'helpers.php'. require_once và include_once ghi nhớ những file đã nạp và bỏ qua chúng ở lần thứ hai, trả về true:

Đầu ra:

int(1)
bool(true)
bool(true)
Hello, Ada

Dùng dạng _once cho các file khai báo, và include bình thường cho template bạn muốn xuất ra nhiều lần. Trong dự án dùng Composer, autoloader tự nạp file lớp cho bạn, nên các lệnh require_once cho lớp gần như biến mất; xem Composer.

Trả về giá trị từ file được include

Một lệnh return ở cấp cao nhất của file được include sẽ dừng file đó và trả một giá trị về cho biểu thức include hoặc require. Nhờ vậy bạn có một file cấu hình gọn gàng: không có biến toàn cục, chỉ là một giá trị bạn gán cho bất kỳ tên nào bạn muốn.

Đầu ra:

My Shop
shop
bool(false)

Các file cấu hình của Laravel (config/app.php, config/database.php và các file khác) hoạt động theo cách này.

Biến và phạm vi trong file được include

Code được include chạy trong phạm vi của dòng include nó. Ở đầu script, nó thấy mọi biến toàn cục; bên trong một hàm, nó chỉ thấy biến cục bộ của hàm đó. Quy tắc thứ hai chính là cách một trình render template nhỏ hoạt động: một hàm có các biến cục bộ đúng bằng những biến mà template cần thấy.

Tab Trang hiển thị cả hai danh sách, được render từ cùng một file template. Vì include chạy bên trong render(), template thấy $heading và $products nhưng không thấy $secret. Dạng foreach ... endforeach dùng trong template là cú pháp thay thế mà PHP cung cấp cho template HTML.

Đường dẫn include và DIR

Một đường dẫn như 'helper.php' không được tính tương đối so với file chứa lệnh include. PHP tìm trong thiết lập include_path (thường bắt đầu bằng ., thư mục làm việc hiện tại) và chỉ sau đó mới tìm trong thư mục của chính file đang include. Vì thế bên trong partials/nav.php, include 'helper.php' có thể nạp một helper.php hoàn toàn khác ở thư mục gốc của dự án. __DIR__, thư mục của file hiện tại, giúp bạn khỏi phải đoán:

Đầu ra:

loaded the root helper.php
loaded partials/helper.php
__DIR__ in nav.php is partials

Hãy viết mọi lệnh include dưới dạng __DIR__ . '/relative/path.php'. Thư mục làm việc phụ thuộc vào cách script được khởi chạy (máy chủ web, cron job, dòng lệnh từ một thư mục khác), nhưng __DIR__ thì không bao giờ thay đổi.

Đừng bao giờ include file do người dùng đặt tên

Một router đầu tay thường đọc tên trang từ URL: include $_GET['page'] . '.php';. Cách này cho phép người truy cập chọn file nào trên máy chủ sẽ chạy, ví dụ ?page=../../config (lỗ hổng local file inclusion), và với thiết lập cũ thì thậm chí cả file từ máy chủ khác. Thay vào đó, hãy ánh xạ các tên được phép sang file. Chạy khối code và bấm vào các liên kết: mỗi lần bấm chạy lại script với một $_GET['page'] khác.

Chỉ ba tên trong $pages mới có thể tới được require; liên kết ../secret nhận trang "Not found". Cách đọc giá trị request an toàn được trình bày trong GETvaˋ_GET và _POST.

Câu hỏi thường gặp

include và require trong PHP khác nhau thế nào?

Cả hai đều nạp và chạy một file PHP khác. Nếu không nạp được file, require dừng script với lỗi nghiêm trọng, còn include in ra cảnh báo, trả về false và để script chạy tiếp. Dùng require cho những file mà trang không thể thiếu, như cấu hình và thư viện hàm.

Khi nào nên dùng require_once thay cho require?

Dùng require_once cho những file định nghĩa hàm, lớp hoặc hằng số. Nạp file như vậy hai lần là lỗi nghiêm trọng (Cannot redeclare), và require_once bỏ qua file nếu nó đã được nạp. Template mà bạn muốn in ra nhiều lần thì dùng include bình thường.

File PHP được include có trả về giá trị được không?

Được. Một lệnh return ở cấp cao nhất của file được include sẽ kết thúc file đó và trở thành giá trị của biểu thức include hoặc require: $config = require 'config.php'; với return ['debug' => true]; trong config.php. Không có return, include cho giá trị 1.

File được include có truy cập được biến của tôi không?

Có. Code được include chạy trong phạm vi của dòng include nó: ở đầu script nó thấy các biến toàn cục, còn bên trong một hàm nó chỉ thấy biến cục bộ của hàm đó. Biến mà nó tạo ra cũng nằm trong cùng phạm vi đó.

Nên viết include('file.php') hay include 'file.php'?

Cả hai đều chạy được, vì include và require là cấu trúc ngôn ngữ, không phải hàm; dấu ngoặc đơn chỉ bao quanh đường dẫn. Phần lớn quy ước code viết require 'file.php'; không có ngoặc.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu