Fix PHP Warning: include() Failed to open stream: No such file or directory

beginner🐘 PHP2026-03-26| PHP 7.x / 8.x trên Linux (Apache/Nginx), Windows (XAMPP/WAMP), macOS

Error Message

Warning: include(config.php): Failed to open stream: No such file or directory in /var/www/html/index.php on line 3
#php#include#require#file-path#stream

Chuyện gì vừa xảy ra

Bạn nhận được cảnh báo này — và có thể là trang trắng hoặc ứng dụng bị lỗi — vì PHP không tìm thấy file mà bạn yêu cầu nó include:

Warning: include(config.php): Failed to open stream: No such file or directory in /var/www/html/index.php on line 3

PHP không thể phân giải config.php thành bất kỳ file nào thực sự tồn tại trên đĩa. Chín trong mười trường hợp, một trong ba vấn đề sau đây xảy ra: file không tồn tại tại đường dẫn đó, thư mục làm việc hiện tại không phải như bạn nghĩ, hoặc đường dẫn bị gõ sai hay không chính xác.

Quy trình debug

Bước 1: Xác định đường dẫn PHP thực sự đang tìm kiếm

Cảnh báo chỉ hiển thị đối số bạn truyền vào — không phải đường dẫn đầy đủ mà PHP cố mở. Thêm một dòng debug nhanh phía trên lệnh include để xem chuyện gì thực sự đang xảy ra:

<?php
echo __DIR__ . '/' . 'config.php' . PHP_EOL;
include('config.php');

Hoặc dùng realpath() để kiểm tra xem file có tồn tại hay không:

<?php
$path = __DIR__ . '/config.php';
var_dump(file_exists($path), $path);

Chạy đoạn này, xem kết quả đầu ra, rồi so sánh với những gì thực sự có trên đĩa.

Bước 2: Kiểm tra thư mục làm việc hiện tại

Đường dẫn tương đối như include('config.php') được phân giải dựa theo thư mục làm việc hiện tại (CWD), không phải tương đối so với file chứa lệnh include. Hai thứ này thường khác nhau. Điều này hay gây nhầm lẫn khi gọi script từ thư mục khác, dùng front controller của framework, hoặc chạy qua CLI.

<?php
echo getcwd(); // In ra thư mục làm việc hiện tại

Kỳ vọng là /var/www/html nhưng lại nhận được /var/www? Đó chính là vấn đề.

Bước 3: Xác nhận file thực sự tồn tại

# Trên Linux/macOS
ls -la /var/www/html/config.php

# Tìm lỗi gõ sai — Linux phân biệt chữ hoa chữ thường
find /var/www/html -name "config*"

Trên Linux, Config.phpconfig.php là hai file khác nhau. Windows không phân biệt chữ hoa chữ thường, nên lỗi gõ sai hoạt động tốt trên XAMPP nhưng sẽ vỡ ngay khi bạn đẩy lên server Linux.

Các cách khắc phục

Cách 1: Dùng DIR để có đường dẫn tương đối đáng tin cậy (khuyến nghị)

Cách này giải quyết hầu hết các trường hợp. __DIR__ là hằng số ma thuật trả về thư mục của file hiện tại — không phải nơi PHP được gọi từ đó.

<?php
// TRƯỚC (dễ vỡ — bị lỗi khi CWD thay đổi)
include('config.php');
include('../lib/helpers.php');

// SAU (đáng tin cậy — luôn tương đối so với file này)
include(__DIR__ . '/config.php');
include(__DIR__ . '/../lib/helpers.php');

Hãy chuyển mọi lệnh include/require tương đối trực tiếp trong project sang dùng __DIR__. Thay đổi đơn giản đó loại bỏ phần lớn lỗi đường dẫn include.

Cách 2: Dùng require thay vì include cho các file quan trọng

Khi config.php là file thiết yếu — thông tin kết nối database, cấu hình ứng dụng, bất cứ thứ gì ứng dụng không thể thiếu — hãy dùng require hoặc require_once thay vì include.

Điểm khác biệt chính: include phát ra Warning và tiếp tục chạy. require ném ra Fatal Error và dừng ngay lập tức. Để PHP tiếp tục chạy âm thầm khi thiếu file config hầu như lúc nào cũng gây ra lỗi thứ hai, khó truy vết hơn, ở 20 dòng sau.

<?php
// Dừng thực thi ngay lập tức nếu config.php bị thiếu
require __DIR__ . '/config.php';

Cách 3: Kiểm tra và sửa đường dẫn file thực tế

CWD đúng nhưng file lại nằm ở chỗ khác? Sửa lại đường dẫn:

<?php
// File nằm tại: /var/www/html/includes/config.php
// Script của bạn nằm tại: /var/www/html/index.php

// Sai
include('config.php');

// Đúng
include __DIR__ . '/includes/config.php';

Cách 4: File thực sự không tồn tại — hãy tạo nó

Đôi khi giải thích đơn giản nhất lại là đúng. Các bản checkout mới thường loại trừ config.php qua .gitignore. Hãy tìm file mẫu:

# Kiểm tra xem có file config mẫu không
ls /var/www/html/config.php.example
ls /var/www/html/config.example.php

# Sao chép và điền giá trị của bạn
cp config.php.example config.php
nano config.php

Cách 5: Quyền truy cập file (ít gặp hơn nhưng có thật)

File tồn tại nhưng PHP không thể mở được:

# Kiểm tra chủ sở hữu và quyền truy cập
ls -la /var/www/html/config.php

# PHP thường chạy với tư cách www-data — cấp quyền đọc cho nó
chown www-data:www-data /var/www/html/config.php
chmod 644 /var/www/html/config.php

Đây là điểm tinh tế: PHP báo "No such file or directory" cho cả hai trường hợp — file không tồn tại và bị từ chối quyền truy cập. Nếu file chắc chắn tồn tại mà cảnh báo vẫn còn, quyền truy cập là thứ cần kiểm tra tiếp theo.

Cách 6: Vấn đề include_path

Một số codebase cũ phụ thuộc vào cài đặt include_path của PHP (cấu hình trong php.ini hoặc qua set_include_path()). Để xem cấu hình hiện tại:

<?php
// Xem include_path hiện tại
echo get_include_path();

// Thêm thư mục của bạn
set_include_path(get_include_path() . PATH_SEPARATOR . '/var/www/html/includes');
include 'config.php'; // PHP giờ tìm kiếm trong includes/ cũng

Tuy nhiên, đừng dựa vào include_path cho các file của ứng dụng — rất dễ vỡ. Hãy dùng đường dẫn __DIR__ tường minh và chỉ dùng include_path cho thư viện hoặc autoload.

Xác nhận

Sau khi áp dụng cách sửa, hãy xác nhận nó thực sự hoạt động trước khi xóa code debug:

<?php
$file = __DIR__ . '/config.php';
if (!file_exists($file)) {
    die('File not found: ' . $file);
}
if (!is_readable($file)) {
    die('File not readable: ' . $file);
}
require $file;
echo 'Config loaded OK';

Khi nó in ra "Config loaded OK", hãy xóa các dòng debug. Sau đó kiểm tra log lỗi PHP để xác nhận cảnh báo đã biến mất:

# Apache
tail -f /var/log/apache2/error.log

# Nginx + PHP-FPM
tail -f /var/log/php8.x-fpm.log

# Hoặc nơi php.ini trỏ đến error_log

Tham khảo nhanh: include vs require

  • include — Phát Warning khi thất bại, tiếp tục thực thi
  • require — Phát Fatal Error khi thất bại, dừng thực thi
  • include_once / require_once — Hành vi tương tự, nhưng bỏ qua nếu file đã được include rồi

Với file config, kết nối database, hoặc bất cứ thứ gì quan trọng: luôn dùng require. Giữ include cho các template fragment tùy chọn.

Bài học rút ra

Sự nhầm lẫn căn bản hầu như luôn giống nhau: nơi PHP được gọi không phải là nơi file chứa lệnh include nằm. Hãy dùng __DIR__. Mọi lúc. Không ngoại lệ.

Viết require __DIR__ . '/something.php' thay vì require 'something.php' và bạn sẽ không bao giờ thấy cảnh báo này nữa.

Nhận bàn giao một codebase đầy lệnh include tương đối trực tiếp? Câu lệnh grep này sẽ cho bạn thấy toàn bộ phạm vi cần dọn dẹp:

grep -rn "include\|require" /var/www/html --include="*.php" | grep -v "__DIR__" | grep -v "vendor/"

Mỗi dòng trong kết quả đó là một lỗi đường dẫn tiềm ẩn đang chờ xảy ra.

Related Error Notes