Menu

strpos() trong PHP: tìm vị trí của chuỗi con

strpos($haystack, $needle) trả về vị trí xuất hiện đầu tiên của $needle, hoặc false nếu không tìm thấy. Tìm hiểu phép kiểm tra !== false, hàm stripos không phân biệt hoa thường, lần xuất hiện cuối cùng với strrpos và cách tìm mọi lần xuất hiệ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.

strpos($haystack, $needle) trả về vị trí của $needle đầu tiên bên trong $haystack, đếm từ 0, hoặc false nếu không có. Luôn kiểm tra kết quả bằng !== false, vì kết quả khớp ở đầu chuỗi trả về 0.

Nếu trên PHP 8 bạn chỉ cần câu trả lời có hoặc không, str_contains() rõ ràng hơn. Dùng strpos() khi vị trí là điều quan trọng.

Cú pháp

strpos(string $haystack, string $needle, int $offset = 0): int|false

Việc tìm kiếm có phân biệt hoa thường. $offset cho biết bắt đầu tìm từ đâu; offset âm được đếm từ cuối chuỗi.

Bẫy !== false

0 và false bằng nhau khi so sánh lỏng (==). Vì vậy, kết quả khớp ở vị trí 0 bị coi là "không tìm thấy" trong mọi phép kiểm tra không nghiêm ngặt.

Quy tắc này cũng áp dụng cho stripos(), strrpos() và array_search(), vì chúng đều có thể trả về 0 cho một kết quả khớp thật.

Tìm không phân biệt hoa thường với stripos

stripos() nhận cùng các đối số và bỏ qua chữ hoa, chữ thường của các chữ cái ASCII.

Tìm lần xuất hiện cuối cùng với strrpos

strrpos() trả về vị trí của kết quả khớp cuối cùng. Đây là cách chuẩn để lấy phần mở rộng của tệp hoặc đoạn cuối của một đường dẫn.

Riêng với tên tệp, pathinfo($file, PATHINFO_EXTENSION) làm sẵn việc này cho bạn. Cách cắt chuỗi tại vị trí tìm được có ở trang substr().

Bắt đầu tìm từ một offset

Đối số thứ ba bỏ qua phần đầu của chuỗi. Offset âm bắt đầu tìm từ chừng ấy ký tự trước cuối chuỗi.

Tìm mọi lần xuất hiện

strpos() chỉ tìm một kết quả. Hãy dùng vòng lặp và dời offset qua từng kết quả để tìm tất cả:

Chỉ cần số lần xuất hiện? substr_count($text, 'the') ngắn gọn hơn. Với mẫu (pattern), preg_match_all() kèm PREG_OFFSET_CAPTURE trả về mọi kết quả khớp cùng vị trí của chúng.

Văn bản tiếng Nhật: vị trí theo byte và vị trí theo ký tự

strpos() tìm đúng văn bản nhiều byte, nhưng con số nó trả về tính theo byte. Mỗi chữ kana và kanji thông dụng chiếm 3 byte trong UTF-8, nên với văn bản toàn tiếng Nhật, vị trí theo byte gấp ba vị trí theo ký tự, còn với văn bản trộn lẫn (kể cả tiếng Việt có dấu) thì hai con số lệch nhau khó đoán hơn. mb_strpos() trả về vị trí theo ký tự, đúng thứ mà mb_substr() cần.

Trộn hai loại là một bug kinh điển: truyền kết quả của strpos() cho mb_substr() sẽ bắt đầu quá xa trong chuỗi. Dùng strpos đi với substr, và mb_strpos đi với mb_substr.

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

strpos() trong PHP trả về gì?

Vị trí của kết quả khớp đầu tiên dưới dạng số nguyên, đếm từ 0, hoặc false nếu không tìm thấy chuỗi cần tìm. strpos('hello', 'l') trả về 2.

Vì sao phải dùng !== false với strpos()?

Vì kết quả khớp ngay ở đầu chuỗi trả về 0, và 0 == false là đúng. if (strpos($s, 'a')) coi kết quả ở vị trí 0 là "không tìm thấy". Luôn so sánh bằng strpos($s, 'a') !== false.

strpos, stripos và strrpos khác nhau thế nào?

strpos() tìm kết quả khớp đầu tiên và phân biệt hoa thường. stripos() tìm kết quả khớp đầu tiên, không phân biệt hoa thường. strrpos() tìm kết quả khớp cuối cùng. strripos() tìm kết quả khớp cuối cùng, không phân biệt hoa thường.

Nên dùng strpos hay str_contains để kiểm tra chuỗi có chứa một đoạn văn bản?

Trên PHP 8, hãy dùng str_contains($haystack, $needle), hàm này trả về đúng true hoặc false và không có bẫy vị trí 0. Dùng strpos() khi bạn cần chính vị trí đó.

Dùng strpos với văn bản tiếng Nhật hay tiếng Việt thế nào?

strpos() tìm đúng văn bản nhiều byte nhưng trả về vị trí tính theo byte. Nếu bạn truyền vị trí đó cho mb_substr() hoặc hiển thị cho người dùng, hãy dùng mb_strpos(), hàm này trả về vị trí tính theo ký tự.

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