Lỗi Gặp Phải
PHP Warning: preg_match(): No ending delimiter '/' found in /var/www/html/app.php on line 23
PHP ném ra cảnh báo này ngay khi cố biên dịch regex nhưng không tìm thấy delimiter đóng. preg_match() trả về false thay vì 0 hoặc 1 — do đó mọi câu lệnh if phía sau sẽ hoạt động sai âm thầm mà bạn không hay biết rằng pattern chưa bao giờ chạy.
Nguyên Nhân
Các hàm PCRE của PHP (preg_match, preg_replace, preg_split, v.v.) yêu cầu một ký tự delimiter bao quanh pattern. Dấu gạch chéo xuôi là lựa chọn thông thường:
/pattern-của-bạn/flags
Có bốn trường hợp kích hoạt cảnh báo này:
- Thiếu hoàn toàn delimiter đóng
- Ký tự delimiter xuất hiện bên trong pattern mà không được escape
- Truyền vào một chuỗi thuần thay vì regex hợp lệ (ví dụ:
"email"thay vì"/email/") - Pattern được tạo động và phép nối chuỗi làm mất delimiter đóng
Cách Sửa Từng Bước
1. Thêm Delimiter Đóng Còn Thiếu
Nguyên nhân phổ biến nhất — có người viết dấu gạch chéo mở nhưng quên dấu đóng:
<?php
// Sai
preg_match('/^[a-z]+', $input);
// Đúng
preg_match('/^[a-z]+/', $input);
2. Escape Delimiter Bên Trong Pattern
Pattern URL là cái bẫy kinh điển. Pattern của bạn chứa ký tự /, PHP đọc ký tự đầu tiên như delimiter đóng, và mọi thứ phía sau trở thành rác:
<?php
// Sai — dấu / trong URL đóng regex ngay sau 'https:'
preg_match('/https://example.com/', $url);
// Phương án A — escape delimiter
preg_match('/https:\/\/example\.com/', $url);
// Phương án B — đổi delimiter (gọn hơn nhiều cho URL)
preg_match('#https://example\.com#', $url);
PHP chấp nhận bất kỳ ký tự không phải chữ-số, không phải backslash, không phải khoảng trắng làm delimiter: /, #, ~, !, |, thậm chí cặp dấu ngoặc như {} hoặc (). Với các pattern chứa URL hoặc đường dẫn file, dùng # giúp bạn khỏi phải escape từng dấu gạch chéo.
3. Sửa Pattern Được Tạo Động
Pattern động là nguồn gốc ngấm ngầm nhất của lỗi này. Ví dụ bạn đang xây dựng bộ lọc tìm kiếm từ khóa từ input của người dùng:
<?php
$keyword = 'error';
// Sai — thiếu hoàn toàn delimiter mở
$pattern = $keyword . '/i';
preg_match($pattern, $log);
// Đúng
$pattern = '/' . preg_quote($keyword, '/') . '/i';
preg_match($pattern, $log);
Luôn bọc nội dung biến bằng preg_quote(). Hàm này escape mọi ký tự đặc biệt trong regex — kể cả delimiter bạn chọn — để các giá trị được chèn vào không thể phá vỡ cấu trúc pattern.
4. Kiểm Tra Chuỗi Thuần Không Có Delimiter
Không có delimiter nào cả cũng là lỗi hay gặp, đặc biệt khi chuyển code cũ từ ereg() (deprecated từ PHP 5.3, bị xóa trong PHP 7):
<?php
// Sai — không có delimiter
preg_match('email', $input);
// Đúng
preg_match('/email/i', $input);
Xác Nhận Đã Sửa Xong
Kiểm tra từ CLI trước — không cần reload ứng dụng:
php -r "var_dump(preg_match('/pattern-của-bạn/', 'chuỗi test'));"
Kết quả sạch trông như sau:
int(0) # không khớp, nhưng không có cảnh báo
int(1) # tìm thấy kết quả khớp
Nếu cảnh báo vẫn còn, PHP in ra trước kết quả int(). Bật báo cáo lỗi đầy đủ để phát hiện mọi vấn đề trong quá trình debug:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
Mẹo Thêm
Lỗi regex rất dễ tạo ra và khó phát hiện trong các pattern dài. Trước khi đẩy code lên production, hãy kiểm tra tương tác. Regex Tester trên ToolCraft cho phép bạn dán pattern theo kiểu PHP, chạy thử với chuỗi mẫu và xem kết quả khớp theo thời gian thực — không có gì rời khỏi trình duyệt của bạn. Tôi dùng công cụ này để phát hiện các lỗi delimiter như thế này trước khi code chạm đến server.
Ba thói quen giúp loại bỏ cảnh báo này vĩnh viễn:
- Dùng
#làm delimiter cho mọi pattern liên quan đến URL hoặc đường dẫn file — không cần escape dấu gạch chéo - Luôn truyền cả hai tham số cho
preg_quote($value, $delimiter)— bỏ tham số thứ hai sẽ không escape delimiter bạn chọn - Trong PHPStorm hoặc VS Code với extension PHP Intelephense, các pattern sai định dạng sẽ được gạch chân trước khi bạn chạy file

