Bài 10. Xử lý chuỗi

Hầu hết dữ liệu web là chuỗi: tên, email, nội dung bài viết, URL. Bài này hệ thống các hàm xử lý chuỗi, lưu ý với tiếng Việt (UTF-8, mb_*), định dạng bằng sprintf, biểu thức chính quy và các hàm làm sạch chuỗi khi hiển thị.

40 phútCơ bản
Bạn sẽ học được
  • Dùng hàm độ dài, cắt, tìm, thay thế, đổi hoa thường
  • Xử lý tiếng Việt đúng với hàm mb_*
  • Định dạng chuỗi với sprintf, str_pad, number_format
  • Dùng preg_match, preg_replace; làm sạch bằng htmlspecialchars, trim

Khái niệm và lý thuyết

Chuỗi PHP là dãy byte; một ký tự tiếng Việt chiếm 2–3 byte trong UTF-8. Các hàm thường (strlen, substr, strtoupper) đếm theo byte nên cắt tiếng Việt có thể vỡ chữ. Dùng họ hàm mb_* (multibyte) cho văn bản tiếng Việt.

Hàm cơ bản

<?php
$s = "  Trường Đại học Tây Bắc  ";
$s = trim($s);                              // bỏ khoảng trắng đầu cuối
echo mb_strlen($s), " ký tự<br>";           // 24
echo mb_strtoupper($s), "<br>";             // TRƯỜNG ĐẠI HỌC TÂY BẮC
echo mb_substr($s, 7, 7), "<br>";           // Đại học
echo str_replace("Tây Bắc", "TBU", $s), "<br>";
echo mb_stripos($s, "tây"), "<br>";         // 15 (không phân biệt hoa thường)
var_dump(str_contains($s, "Đại"), str_starts_with($s, "Trường"), str_ends_with($s, "Bắc"));
echo ucfirst("xin chào"), " ", mb_convert_case("lò văn an", MB_CASE_TITLE), "<br>";
echo strrev("abc"), " ", str_repeat("-", 10), " ", wordwrap($s, 10, "<br>", true);
$tu = explode(" ", $s);  echo count($tu), " từ, từ cuối: ", end($tu);

Định dạng chuỗi

<?php
printf("%s có điểm %.2f, xếp thứ %03d<br>", "An", 8.456, 7);   // An có điểm 8.46, xếp thứ 007
$dong = sprintf("%-10s|%5.1f|", "Toán", 8.5);                  // căn trái 10, số 5 ký tự
echo str_pad("5", 3, "0", STR_PAD_LEFT);                         // 005
echo number_format(1234567.5, 1, ",", ".");                      // 1.234.567,5
echo nl2br("Dòng 1\nDòng 2");                                    // thêm <br> trước xuống dòng
echo strip_tags("<b>đậm</b> thường");                            // đậm thường

Biểu thức chính quy

<?php
$sdt = "0912345678";
if (preg_match('/^0[0-9]{9}$/', $sdt)) echo "Số hợp lệ<br>";
preg_match('/^(\w+)@(\w+\.\w+)$/', "Địa chỉ email này đang được bảo vệ từ spam bots, bạn cần kích hoạt Javascript để xem nó. Bạn cần kích hoạt Javascript để xem nó.", $m);  print_r($m);
echo preg_replace('/\s+/', ' ', "nhiều    khoảng   trắng");   // gộp khoảng trắng
$slug = strtolower(trim(preg_replace('/[^a-z0-9]+/i', '-', "Hoc PHP co ban!"), '-')); // hoc-php-co-ban
preg_match_all('/#(\w+)/u', "học #php và #mysql", $tags);  print_r($tags[1]);

Thêm cờ u khi xử lý tiếng Việt. Thử mẫu tại regex101.com (chọn PHP/PCRE).

Làm sạch chuỗi khi hiển thị

<?php
$binh_luan = '<script>alert("xss")</script> Bài hay!';
echo htmlspecialchars($binh_luan, ENT_QUOTES, 'UTF-8');   // hiển thị an toàn
function e(string $s): string { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); }
echo "<p>" . e($_GET["q"] ?? "") . "</p>";
echo urlencode("tây bắc & sơn la");          // t%C3%A2y+b%E1%BA%AFc+%26+s%C6%A1n+la
echo filter_var("  Địa chỉ email này đang được bảo vệ từ spam bots, bạn cần kích hoạt Javascript để xem nó. Bạn cần kích hoạt Javascript để xem nó. ", FILTER_VALIDATE_EMAIL) ? "email ok" : "sai";
Mẹo hay

Viết sẵn hàm e() như trên và dùng mọi nơi có hiển thị dữ liệu người dùng: đây là cách chống XSS đơn giản mà hiệu quả.

Lưu ý

Không bao giờ echo trực tiếp dữ liệu từ $_GET, $_POST hay CSDL ra HTML mà không qua htmlspecialchars.

Thực hành
  1. Viết hàm tạo slug tiếng Việt không dấu (dùng bảng chuyển hoặc iconv) cho tiêu đề bài viết.
  2. Kiểm tra mã sinh viên dạng SV + 6 số bằng preg_match.
  3. Cắt mô tả bài viết còn 100 ký tự, thêm “...” (mb_substr), không vỡ chữ.
  4. In bảng điểm thẳng cột bằng sprintf trong thẻ pre.
Tóm tắt bài học
  • Dùng mb_* cho tiếng Việt.
  • trim, str_replace, explode/implode, str_contains là nhóm dùng nhiều.
  • sprintf/printf, number_format định dạng.
  • preg_* cho mẫu phức tạp; htmlspecialchars khi hiển thị.