Cách khai báo và xử lý dữ liệu chuỗi trong PHP

PHP Tutorial | by Học PHP

Chuỗi (String) – một trong những kiểu dữ liệu cơ bản và được sử dụng nhiều nhất trong mọi ngôn ngữ lập trình, đặc biệt là PHP. Chuỗi là tập hợp của các ký tự, từ những dòng chữ đơn giản bạn thấy trên website cho đến những đoạn mã HTML phức tạp hay truy vấn cơ sở dữ liệu.Việc hiểu rõ cách khai báo, thao tác và xử lý chuỗi một cách hiệu quả và an toàn không chỉ giúp bạn viết code gọn gàng, mà còn là chìa khóa để bảo vệ ứng dụng của bạn khỏi các lỗ hổng bảo mật tiềm ẩn.

Trong bài viết này, mình sẽ cùng nhau tìm hiểu mọi khía cạnh của chuỗi trong PHP: từ những cách khai báo khác nhau, các phép toán cơ bản, đến vô vàn hàm xử lý chuỗi mạnh mẽ mà PHP cung cấp. Hãy cùng bắt đầu để làm chủ "văn bản" trong PHP nhé!

Chuỗi là gì?

Trong lập trình, chuỗi (String) là một kiểu dữ liệu dùng để lưu trữ và biểu diễn văn bản. Bạn có thể hình dung chuỗi như một "dãy" các ký tự được sắp xếp theo một thứ tự nhất định. Mỗi ký tự có thể là một chữ cái, một con số, một ký hiệu, một dấu cách, hoặc bất kỳ ký tự đặc biệt nào mà bạn có thể gõ trên bàn phím.

Ví dụ:

  • "Hello World!" là một chuỗi.
  • "12345" cũng là một chuỗi (mặc dù trông giống số, nó được định nghĩa là chuỗi).
  • "Đây là một câu nói." cũng là một chuỗi.

Tầm quan trọng trong lập trình web: Trong môi trường lập trình web, chuỗi là "vua" bởi vì hầu hết mọi thứ chúng ta nhìn thấy hoặc tương tác trên internet đều là văn bản. Chuỗi đóng vai trò cốt lõi trong rất nhiều khía cạnh:

  • Xử lý nội dung văn bản: Mọi bài viết, tiêu đề, mô tả sản phẩm, bình luận trên website đều được lưu trữ và xử lý dưới dạng chuỗi.
  • Dữ liệu form: Khi người dùng nhập thông tin vào các trường (input) trên form (tên, email, mật khẩu), dữ liệu này sẽ được gửi đến máy chủ PHP dưới dạng chuỗi.
  • Thông báo lỗi và thông báo cho người dùng: Các thông báo như "Đăng nhập thành công!", "Mật khẩu không đúng.", "Sản phẩm đã được thêm vào giỏ hàng." đều là các chuỗi.
  • Truy vấn SQL: Khi bạn muốn lấy hoặc lưu trữ dữ liệu vào cơ sở dữ liệu, các câu lệnh truy vấn (ví dụ: SELECT * FROM users WHERE name = 'John') đều là các chuỗi.
  • HTML output: PHP tạo ra nội dung HTML để gửi về trình duyệt của người dùng, và HTML về cơ bản là một chuỗi dài chứa các thẻ và văn bản.
  • JSON/XML data: Khi trao đổi dữ liệu giữa máy chủ và các ứng dụng khác (ví dụ: JavaScript trên frontend, ứng dụng di động), định dạng JSON hoặc XML thường được sử dụng, và chúng cũng được biểu diễn dưới dạng chuỗi.

Đặc điểm của chuỗi trong PHP

PHP xử lý chuỗi một cách khá linh hoạt và mạnh mẽ, với một vài đặc điểm nổi bật:

PHP không có giới hạn độ dài chuỗi cố định: Khác với một số ngôn ngữ khác có thể yêu cầu bạn khai báo trước độ dài tối đa của chuỗi, PHP cho phép chuỗi có độ dài gần như không giới hạn, chỉ bị giới hạn bởi lượng bộ nhớ (RAM) mà máy chủ của bạn có sẵn để cấp phát cho chương trình PHP. Điều này rất tiện lợi vì bạn không cần phải lo lắng về việc chuỗi quá dài sẽ gây lỗi tràn bộ nhớ (buffer overflow) trong các tác vụ thông thường.

<?php
$chuoiNgan = "Hello";
echo "Độ dài chuỗi ngắn: " . strlen($chuoiNgan) . " ký tự.<br>";

// Tạo một chuỗi rất dài (ví dụ 1MB)
$chuoiRatDai = str_repeat("A", 1024 * 1024); // Lặp lại ký tự 'A' 1 triệu lần
echo "Độ dài chuỗi rất dài (1MB): " . strlen($chuoiRatDai) . " ký tự.<br>";
// PHP sẽ xử lý chuỗi này miễn là có đủ bộ nhớ.
?>

Chuỗi có thể chứa bất kỳ ký tự nào: Một chuỗi trong PHP có thể chứa bất kỳ ký tự hợp lệ nào, bao gồm:

  • Chữ cái: a-z, A-Z (kể cả các ký tự có dấu như tiếng Việt: á, à, ã, ...).
  • Số: 0-9.
  • Ký hiệu: !, @, #, $, %, ^, &, *, (, ), -, _, =, +, [, ], {, }, \, |, ;, :, ', ", ,, <, ., >, /, ?, ~.
  • Ký tự đặc biệt/không in được: Như ký tự xuống dòng (\n), tab (\t), hoặc các ký tự Unicode phức tạp.
<?php
$chuoiKyTuKhacNhau = "Đây là 1 chuỗi với các ký tự đặc biệt: !@#$%^&*() và số 123.";
echo $chuoiKyTuKhacNhau . "<br>";

$chuoiTiengViet = "Xin chào Việt Nam! Học lập trình PHP.";
echo $chuoiTiengViet . "<br>";

// Chuỗi có ký tự xuống dòng (sử dụng nháy kép để nhận diện \n)
$chuoiNhieuDong = "Dòng thứ nhất.\nDòng thứ hai.\tCó tab.";
echo $chuoiNhieuDong . "<br>";
?>

(Lưu ý: Để hiển thị \n xuống dòng trên trình duyệt web, bạn thường cần dùng thẻ <br> của HTML hoặc bọc trong thẻ <pre> nếu muốn giữ nguyên định dạng văn bản thô).

Cách khai báo chuỗi trong PHP

PHP cung cấp bốn cách chính để bạn có thể khai báo một chuỗi, mỗi cách có những đặc điểm và ưu điểm riêng, phù hợp với từng tình huống cụ thể.

Dấu nháy đơn (' ')

Đặc điểm: Khi bạn bao quanh chuỗi bằng dấu nháy đơn, PHP sẽ xử lý chuỗi đó một cách "nguyên văn" (literal). Điều này có nghĩa là:

  • Không nội suy biến: Các biến nằm trong chuỗi sẽ không được thay thế bằng giá trị của chúng.
  • Không xử lý hầu hết các ký tự thoát: Các ký tự đặc biệt như \n (xuống dòng) hay \t (tab) sẽ không được PHP hiểu là lệnh thoát mà được in ra đúng như bạn gõ. Ngoại lệ duy nhất là \' để thoát dấu nháy đơn bên trong chuỗi, và \\ để in ra dấu gạch chéo ngược.

Ưu điểm:

  • Nhanh hơn một chút: Do PHP không phải kiểm tra và xử lý nội suy biến hay ký tự thoát, việc xử lý chuỗi nháy đơn có thể nhanh hơn một chút so với nháy kép. Mặc dù sự khác biệt này thường không đáng kể trong các ứng dụng thông thường, nhưng nó có thể có ý nghĩa trong các vòng lặp lớn hoặc các ứng dụng hiệu suất cao.
  • Hữu ích khi chuỗi không chứa biến hoặc ký tự thoát: Đây là lựa chọn tốt nhất khi bạn chỉ cần một chuỗi văn bản thuần túy.

Ví dụ Code:

<?php
$productName = 'Laptop Dell XPS';
$price = 25000000;

// Chuỗi nháy đơn bình thường
echo 'Đây là một chuỗi được khai báo bằng nháy đơn.<br>';

// Minh họa không nội suy biến
echo 'Giá của $productName là $price VNĐ.<br>';
// Kết quả: Giá của $productName là $price VNĐ. (biến không được thay thế)

// Minh họa không xử lý ký tự thoát
echo 'Dòng đầu tiên.\nĐây là dòng thứ hai.\tCó một tab ở đây.\\<br>';
// Kết quả: Dòng đầu tiên.\nĐây là dòng thứ hai.\tCó một tab ở đây.\ (in ra cả \n và \t)

// Cách thoát dấu nháy đơn bên trong chuỗi nháy đơn
echo 'Anh ấy nói: \'Chào bạn!\'.<br>';
// Kết quả: Anh ấy nói: 'Chào bạn!'.
?>

Dấu nháy kép (" ")

Đặc điểm: Khi bạn bao quanh chuỗi bằng dấu nháy kép, PHP sẽ xử lý chuỗi đó linh hoạt hơn nhiều.

  • Hỗ trợ nội suy biến (Variable Interpolation): PHP sẽ tìm kiếm các biến (bắt đầu bằng $) trong chuỗi và tự động thay thế chúng bằng giá trị hiện tại của biến đó.
  • Hỗ trợ xử lý ký tự thoát (Escape Sequences): PHP sẽ nhận diện và chuyển đổi các ký tự đặc biệt bắt đầu bằng dấu gạch chéo ngược (\) thành ý nghĩa tương ứng của chúng. Các ký tự thoát phổ biến:
    • \n: Xuống dòng (newline)
    • \r: Về đầu dòng (carriage return)
    • \t: Tab ngang
    • \\: Ký tự gạch chéo ngược
    • \": Dấu nháy kép literal (để in ra dấu nháy kép bên trong chuỗi nháy kép)
    • \$: Ký tự đô la literal (để in ra dấu $ mà không hiểu là biến)

Ưu điểm:

  • Linh hoạt hơn: Dễ dàng kết hợp giá trị của các biến vào trong chuỗi mà không cần phải dùng toán tử nối chuỗi (.).
  • Dễ đọc hơn: Đối với các chuỗi có chứa biến hoặc các ký tự đặc biệt cần được thoát.

Ví dụ Code:

<?php
$userName = "Mai Anh";
$age = 25;
$city = "Hà Nội";

// Nội suy biến trong nháy kép
echo "Chào mừng $userName, bạn $age tuổi và đang sống tại $city.<br>";
// Kết quả: Chào mừng Mai Anh, bạn 25 tuổi và đang sống tại Hà Nội.

// Sử dụng ký tự thoát
echo "Dòng thứ nhất.\n"; // \n sẽ tạo ra một dòng mới trong output (nếu là plain text)
echo "Dòng thứ hai\t(có tab).\n"; // \t sẽ tạo một khoảng trắng tab
echo "Đường dẫn: C:\\Program Files\\PHP\\<br>"; // \\ để in ra một dấu \
echo "Anh ấy nói: \"Tôi thích PHP!\".<br>"; // \" để in ra dấu "

// In ra ký tự đô la literal
echo "Giá tiền là \$100 đô la.<br>"; // \$ để in ra ký tự $
?>
  • (Lưu ý: Khi xem trên trình duyệt, \n\t sẽ chỉ hiển thị hiệu quả nếu bạn xem mã nguồn trang (View Page Source) hoặc bọc nội dung trong thẻ <pre> của HTML. Để xuống dòng trong HTML, bạn thường dùng thẻ <br>).

Heredoc syntax (<<<)

Đặc điểm: Heredoc là một cú pháp đặc biệt để khai báo chuỗi, được thiết kế cho các chuỗi dài, nhiều dòng hoặc chứa nhiều dấu nháy mà không muốn phải thoát từng ký tự. Nó hoạt động tương tự như chuỗi được bao quanh bởi dấu nháy kép:

  • Hỗ trợ nội suy biến.
  • Hỗ trợ xử lý ký tự thoát.

Cú pháp:

  • Bắt đầu bằng <<< theo sau là một định danh (identifier). Định danh này là một chuỗi tùy ý, không có khoảng trắng, và thường viết hoa để dễ phân biệt.
  • Nội dung chuỗi nằm giữa dòng bắt đầu và dòng kết thúc.
  • Kết thúc bằng định danh ban đầu, theo sau là dấu chấm phẩy (;), và phải nằm ở đầu dòng, không có bất kỳ khoảng trắng nào trước nó. Điều này cực kỳ quan trọng, nếu không sẽ gây lỗi cú pháp.

Ưu điểm:

  • Dễ đọc hơn cho các khối văn bản lớn: Đặc biệt hữu ích khi bạn cần nhúng các đoạn mã HTML, XML, JSON hoặc các truy vấn SQL dài vào code PHP mà không muốn "nhảy" qua lại giữa nháy kép và nháy đơn, hay phải thoát nhiều ký tự đặc biệt.

Ví dụ Code:

<?php
$websiteName = "My Awesome Site";
$adminEmail = "[email protected]";

echo "<h3>Sử dụng Heredoc để tạo khối HTML:</h3>";
echo <<<HTML_BLOCK
<!DOCTYPE html>
<html lang="vi">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>$websiteName</title>
    <style>
        body { font-family: Arial, sans-serif; }
        .footer { color: gray; }
    </style>
</head>
<body>
    <h1>Chào mừng đến với $websiteName!</h1>
    <p>Đây là nội dung được tạo bằng Heredoc syntax.</p>
    <p>Bạn có thể liên hệ chúng tôi tại: $adminEmail</p>
    <p class="footer">Bản quyền &copy; 2025.</p>
</body>
</html>
HTML_BLOCK; // Định danh kết thúc phải nằm ở đầu dòng và theo sau bởi dấu chấm phẩy
?>

Nowdoc syntax (<<<' ')

Đặc điểm: Nowdoc là một cú pháp tương tự Heredoc, nhưng nó hoạt động giống như chuỗi được bao quanh bởi dấu nháy đơn. Điều này có nghĩa là:

  • KHÔNG nội suy biến.
  • KHÔNG xử lý ký tự thoát.
  • Nó yêu cầu PHP phiên bản 5.3 trở lên.

Cú pháp:

  • Bắt đầu bằng <<< theo sau là một định danh được bao trong dấu nháy đơn (<<<'IDENTIFIER').
  • Nội dung chuỗi nằm giữa dòng bắt đầu và dòng kết thúc.
  • Kết thúc bằng định danh ban đầu, theo sau là dấu chấm phẩy (;), và phải nằm ở đầu dòng, không có bất kỳ khoảng trắng nào trước nó.

Ưu điểm:

  • Rất hữu ích khi bạn muốn in một khối văn bản chứa nhiều ký tự đặc biệt (bao gồm cả dấu $ hoặc \) mà không muốn PHP hiểu lầm chúng là biến hay ký tự thoát. Nó đảm bảo rằng nội dung được in ra chính xác như bạn gõ.

Ví dụ Code:

<?php
$username = "john_doe";
$password = "P@ssw0rd123$"; // Chuỗi chứa ký tự $ và @

echo "<h3>Sử dụng Nowdoc để in khối văn bản nguyên văn:</h3>";
echo <<<'CONFIG_BLOCK'
# Cấu hình cơ sở dữ liệu
DB_HOST = localhost
DB_USER = root
DB_PASS = P@ssw0rd123$
DB_NAME = my_database

# Đường dẫn thư mục
UPLOAD_DIR = /var/www/html/uploads/
CACHE_DIR = /tmp/cache/

# Biến PHP sẽ không được nội suy ở đây: $username và $password
CONFIG_BLOCK; // Định danh kết thúc phải nằm ở đầu dòng
?>

Trong ví dụ Nowdoc trên, $username$password sẽ được in ra đúng như vậy, không phải giá trị của biến.

Các phép toán và thao tác cơ cản với chuỗi trong PHP

Sau khi đã biết cách khai báo chuỗi, việc tiếp theo là tìm hiểu cách chúng ta có thể làm việc với chúng, từ ghép nối đến so sánh hay truy cập từng ký tự.

Nối chuỗi (Concatenation)

  • Toán tử chấm (.): Trong PHP, bạn sử dụng toán tử chấm (.) để nối (ghép) hai hoặc nhiều chuỗi lại với nhau, tạo thành một chuỗi mới.

Ví dụ Code:

<?php
$firstName = "John";
$lastName = "Doe";
$fullName = $firstName . " " . $lastName; // Nối chuỗi biến và chuỗi ký tự
echo "Tên đầy đủ: " . $fullName . "<br>"; // Output: Tên đầy đủ: John Doe

$greeting = "Xin chào";
$person = "Thế giới";
$message = $greeting . ", " . $person . "!";
echo $message . "<br>"; // Output: Xin chào, Thế giới!

// Nối chuỗi và số (PHP tự động chuyển đổi số thành chuỗi)
$product = "Áo phông";
$price = 150000;
echo "Sản phẩm: " . $product . " - Giá: " . $price . " VNĐ.<br>"; // Output: Sản phẩm: Áo phông - Giá: 150000 VNĐ.
?>

Độ dài chuỗi

Xác định độ dài của một chuỗi là một thao tác rất phổ biến. Tuy nhiên, với các ngôn ngữ hỗ trợ Unicode như tiếng Việt, bạn cần lưu ý đến sự khác biệt giữa "số byte" và "số ký tự".

  • strlen(): Hàm này trả về độ dài chuỗi theo số byte. Đối với các ký tự ASCII (tiếng Anh không dấu), 1 ký tự = 1 byte, nên strlen() sẽ cho kết quả đúng số ký tự. Tuy nhiên, đối với các chuỗi Unicode/UTF-8 (ví dụ: tiếng Việt có dấu), một ký tự có thể chiếm nhiều hơn 1 byte, do đó strlen() sẽ trả về số byte chứ không phải số ký tự thực tế.

  • mb_strlen(): Đây là hàm an toàn cho các chuỗi đa byte (MultiByte String). Nó trả về số lượng ký tự thực tế trong chuỗi, rất quan trọng khi làm việc với tiếng Việt hoặc các ngôn ngữ khác có ký tự đặc biệt. Để sử dụng mb_strlen() và các hàm mb_* khác, bạn cần đảm bảo rằng mb_string extension đã được bật trong cấu hình PHP (php.ini).

Ví dụ Code:

<?php
$englishString = "Hello";
$vietnameseString = "Xin chào Việt Nam"; // "c" có dấu nặng (chữ "o" có mũ, chữ "a" có mũ), ...

echo "Độ dài của chuỗi tiếng Anh 'Hello':<br>";
echo " - strlen(): " . strlen($englishString) . " (bytes/ký tự)<br>";   // Output: 5
echo " - mb_strlen(): " . mb_strlen($englishString) . " (ký tự)<br>"; // Output: 5

echo "Độ dài của chuỗi tiếng Việt 'Xin chào Việt Nam':<br>";
echo " - strlen(): " . strlen($vietnameseString) . " (bytes) - KHÔNG ĐÚNG SỐ KÝ TỰ THỰC TẾ!<br>";
// Output: Ví dụ: 19-20 (phụ thuộc vào bộ mã hóa, vì 'chào' là 4 ký tự nhưng có thể là 6-8 byte)

echo " - mb_strlen(): " . mb_strlen($vietnameseString, 'UTF-8') . " (ký tự)<br>";
// Output: 17 (đúng số ký tự thực tế: X i n   c h à o   V i ệ t   N a m = 17 ký tự)
// Luôn chỉ định encoding, thường là 'UTF-8'
?>

Truy cập ký tự

Bạn có thể truy cập từng ký tự trong một chuỗi bằng cách coi nó như một mảng ký tự, sử dụng offset (chỉ mục) đặt trong dấu ngoặc vuông []. Chỉ mục bắt đầu từ 0 cho ký tự đầu tiên.

  • Lưu ý: Tương tự như strlen(), việc truy cập ký tự trực tiếp bằng offset ($string[0]) cũng có thể không an toàn hoặc cho kết quả không mong muốn với các chuỗi UTF-8 nếu ký tự đó là đa byte. Nếu bạn cần xử lý từng ký tự một cách an toàn với UTF-8, hãy cân nhắc sử dụng mb_substr() với độ dài 1 hoặc chuyển đổi chuỗi thành mảng các ký tự bằng mb_str_split() (PHP 7.4+).

Ví dụ Code:

<?php
$word = "Hello";
echo "Ký tự đầu tiên của 'Hello': " . $word[0] . "<br>";  // Output: H
echo "Ký tự thứ ba của 'Hello': " . $word[2] . "<br>";   // Output: l
echo "Ký tự cuối cùng của 'Hello': " . $word[strlen($word) - 1] . "<br>"; // Output: o

// Cảnh báo với UTF-8 (tiếng Việt)
$vietnameseWord = "Chào";
echo "Ký tự đầu tiên của 'Chào': " . $vietnameseWord[0] . "<br>"; // Output: C
echo "Ký tự thứ hai của 'Chào': " . $vietnameseWord[1] . "<br>"; // Output: h
echo "Ký tự thứ ba của 'Chào': " . $vietnameseWord[2] . "<br>"; // Output:  (có thể là một phần của ký tự 'à' hoặc 'a' có dấu)
// Để truy cập an toàn, nên dùng mb_substr()
echo "Ký tự thứ ba của 'Chào' (an toàn UTF-8): " . mb_substr($vietnameseWord, 2, 1, 'UTF-8') . "<br>"; // Output: à
?>

So sánh chuỗi

So sánh chuỗi là việc kiểm tra xem hai chuỗi có giống nhau hay không, hoặc chuỗi nào "lớn hơn" hay "nhỏ hơn" chuỗi kia theo thứ tự từ điển.

Toán tử so sánh (==, !=, <, >): Các toán tử này so sánh chuỗi theo thứ tự từ điển (lexicographical), nghĩa là so sánh từng ký tự một dựa trên giá trị ASCII (hoặc giá trị byte) của chúng.

  • == (bằng): true nếu hai chuỗi giống hệt nhau.
  • != (khác): true nếu hai chuỗi khác nhau.
  • <, >: So sánh theo thứ tự bảng chữ cái.
  • Lưu ý quan trọng: So sánh bằng == không phân biệt kiểu dữ liệu. Nếu bạn so sánh một chuỗi số với một số ("123" == 123), PHP sẽ tự động chuyển đổi kiểu. Để so sánh cả giá trị và kiểu dữ liệu, hãy dùng === (toán tử nhận dạng chặt chẽ).

Hàm strcmp(): Hàm này thực hiện so sánh chuỗi có phân biệt chữ hoa/thường. Nó trả về:

  • 0: Nếu hai chuỗi giống hệt nhau.
  • < 0 (số âm): Nếu chuỗi thứ nhất nhỏ hơn chuỗi thứ hai.
  • > 0 (số dương): Nếu chuỗi thứ nhất lớn hơn chuỗi thứ hai.

Hàm strcasecmp(): Hàm này thực hiện so sánh chuỗi không phân biệt chữ hoa/thường. Nó cũng trả về 0, số âm, hoặc số dương tương tự như strcmp().

Ví dụ Code:

<?php
$str1 = "apple";
$str2 = "Apple";
$str3 = "banana";
$numStr = "123";
$numInt = 123;

echo "<h3>So sánh bằng toán tử:</h3>";
echo "Is '$str1' == '$str2'? " . ($str1 == $str2 ? "True" : "False") . "<br>"; // Output: False (phân biệt hoa thường)
echo "Is '$str1' == 'apple'? " . ($str1 == 'apple' ? "True" : "False") . "<br>"; // Output: True
echo "Is '$str1' < '$str3'? " . ($str1 < $str3 ? "True" : "False") . "<br>";     // Output: True ('apple' nhỏ hơn 'banana')

echo "Is '$numStr' == $numInt? " . ($numStr == $numInt ? "True" : "False") . "<br>"; // Output: True (ép kiểu ngầm định)
echo "Is '$numStr' === $numInt? " . ($numStr === $numInt ? "True" : "False") . "<br>"; // Output: False (kiểu khác nhau)

echo "<h3>So sánh bằng hàm:</h3>";
// strcmp(): phân biệt chữ hoa/thường
echo "strcmp('$str1', '$str2') (apple vs Apple): " . strcmp($str1, $str2) . "<br>"; // Output: 32 (apple > Apple)
echo "strcmp('$str1', 'apple') (apple vs apple): " . strcmp($str1, 'apple') . "<br>"; // Output: 0
echo "strcmp('$str3', '$str1') (banana vs apple): " . strcmp($str3, $str1) . "<br>"; // Output: -1 (banana > apple -> số dương)
                                                                                     // (kết quả số cụ thể phụ thuộc vào phiên bản PHP và bảng mã)

// strcasecmp(): không phân biệt chữ hoa/thường
echo "strcasecmp('$str1', '$str2') (apple vs Apple): " . strcasecmp($str1, $str2) . "<br>"; // Output: 0
echo "strcasecmp('$str1', 'APPLE') (apple vs APPLE): " . strcasecmp($str1, 'APPLE') . "<br>"; // Output: 0
?>

Các hàm xử lý chuỗi phổ biến trong PHP

PHP có một bộ sưu tập khổng lồ các hàm tích hợp sẵn để thao tác và xử lý chuỗi. Dưới đây là một số hàm quan trọng và được sử dụng thường xuyên nhất.

Tìm kiếm và thay thế

  • strpos(string $haystack, string $needle, int $offset = 0): int|false: Tìm vị trí xuất hiện đầu tiên của một chuỗi con ($needle) trong một chuỗi lớn ($haystack). Trả về chỉ mục (offset) của vị trí tìm thấy (bắt đầu từ 0) hoặc false nếu không tìm thấy. $offset là vị trí bắt đầu tìm kiếm.

  • str_replace(mixed $search, mixed $replace, mixed $subject, int &$count = null): string|array: Thay thế tất cả các lần xuất hiện của một chuỗi con ($search) bằng một chuỗi khác ($replace) trong một chuỗi gốc ($subject). Có thể thay thế nhiều chuỗi cùng lúc bằng cách truyền mảng cho $search$replace. Biến $count (truyền tham chiếu) sẽ lưu trữ số lần thay thế được thực hiện.

  • substr(string $string, int $start, ?int $length = null): string|false: Trích xuất một chuỗi con từ một chuỗi gốc.

    • $string: Chuỗi gốc.
    • $start: Vị trí bắt đầu (có thể âm, đếm từ cuối chuỗi).
    • $length: Chiều dài của chuỗi con muốn trích xuất (nếu bỏ qua, sẽ trích xuất đến hết chuỗi).
  • explode(string $separator, string $string, int $limit = PHP_INT_MAX): array: Chia một chuỗi thành một mảng các chuỗi con dựa trên một ký tự hoặc chuỗi phân cách ($separator).

    • $limit: Số phần tử tối đa trong mảng kết quả.
  • implode(string $separator, array $array): string: Ngược lại với explode(), hàm này nối các phần tử của một mảng thành một chuỗi duy nhất, với các phần tử được phân cách bởi $separator.

Ví dụ Code:

<?php
echo "<h3>1. Tìm kiếm và thay thế:</h3>";
$text = "Học PHP rất thú vị. PHP là ngôn ngữ lập trình web phổ biến.";

// strpos()
$pos = strpos($text, "PHP");
echo "Vị trí đầu tiên của 'PHP': " . ($pos !== false ? $pos : "Không tìm thấy") . "<br>"; // Output: 4
$pos2 = strpos($text, "Python");
echo "Vị trí của 'Python': " . ($pos2 !== false ? $pos2 : "Không tìm thấy") . "<br>"; // Output: Không tìm thấy

// str_replace()
$newText = str_replace("PHP", "JavaScript", $text);
echo "Sau khi thay thế 'PHP' bằng 'JavaScript': " . $newText . "<br>";
// Output: Học JavaScript rất thú vị. JavaScript là ngôn ngữ lập trình web phổ biến.

$count = 0;
$replaceMultiple = str_replace(["PHP", "ngôn ngữ"], ["Node.js", "nguồn mở"], $text, $count);
echo "Thay thế nhiều từ: " . $replaceMultiple . "<br>";
echo "Số lần thay thế: " . $count . "<br>";

// substr()
$sub = substr($text, 4, 3); // Bắt đầu từ vị trí 4, lấy 3 ký tự
echo "Chuỗi con từ vị trí 4, dài 3 ký tự: " . $sub . "<br>"; // Output: PHP

$subFromEnd = substr($text, -8); // Lấy 8 ký tự từ cuối chuỗi
echo "8 ký tự cuối cùng: " . $subFromEnd . "<br>"; // Output: phổ biến.

// explode()
$sentence = "Hello,world,how,are,you?";
$words = explode(",", $sentence);
echo "Mảng sau khi explode: ";
print_r($words);
echo "<br>";

$parts = explode(" ", $text, 3); // Chia tối đa 3 phần
echo "Chia chuỗi thành 3 phần: ";
print_r($parts);
echo "<br>";

// implode()
$arr = ["Apple", "Banana", "Cherry"];
$fruitString = implode(" - ", $arr);
echo "Chuỗi sau khi implode: " . $fruitString . "<br>"; // Output: Apple - Banana - Cherry
?>

Chuyển đổi định dạng

  • strtolower(string $string): string: Chuyển đổi tất cả các ký tự trong chuỗi sang chữ thường.

  • strtoupper(string $string): string: Chuyển đổi tất cả các ký tự trong chuỗi sang chữ hoa.

    • Lưu ý: Cả strtolower()strtoupper() hoạt động tốt với ký tự ASCII. Đối với ký tự Unicode (tiếng Việt có dấu), bạn nên dùng mb_strtolower()mb_strtoupper().
  • ucfirst(string $string): string: Chuyển đổi ký tự đầu tiên của chuỗi thành chữ hoa.

  • ucwords(string $string): string: Chuyển đổi ký tự đầu tiên của mỗi từ trong chuỗi thành chữ hoa.

  • trim(string $string, string $characters = " \t\n\r\0\x0B"): string: Xóa khoảng trắng (hoặc các ký tự khác được chỉ định) ở đầu và cuối chuỗi.

  • ltrim(string $string, string $characters = " \t\n\r\0\x0B"): string: Xóa khoảng trắng (hoặc các ký tự khác được chỉ định) ở đầu chuỗi (left trim).

  • rtrim(string $string, string $characters = " \t\n\r\0\x0B"): string: Xóa khoảng trắng (hoặc các ký tự khác được chỉ định) ở cuối chuỗi (right trim).

Ví dụ Code:

<?php
echo "<h3>2. Chuyển đổi định dạng:</h3>";
$textCase = "Hello World! this is PHP.";

// Chuyển đổi chữ thường/hoa
echo "strtolower(): " . strtolower($textCase) . "<br>"; // Output: hello world! this is php.
echo "strtoupper(): " . strtoupper($textCase) . "<br>"; // Output: HELLO WORLD! THIS IS PHP.

// Viết hoa ký tự đầu
echo "ucfirst(): " . ucfirst(strtolower($textCase)) . "<br>"; // Output: Hello world! this is php.

// Viết hoa ký tự đầu mỗi từ
echo "ucwords(): " . ucwords(strtolower($textCase)) . "<br>"; // Output: Hello World! This Is Php.

// Xóa khoảng trắng
$paddedText = "   Đây là văn bản có khoảng trắng thừa.   ";
echo "Chuỗi gốc: '" . $paddedText . "'<br>";
echo "trim(): '" . trim($paddedText) . "'<br>";   // Output: 'Đây là văn bản có khoảng trắng thừa.'
echo "ltrim(): '" . ltrim($paddedText) . "'<br>"; // Output: 'Đây là văn bản có khoảng trắng thừa.   '
echo "rtrim(): '" . rtrim($paddedText) . "'<br>"; // Output: '   Đây là văn bản có khoảng trắng thừa.'

// Xóa ký tự tùy chỉnh
$customTrim = "---Hello World---";
echo "trim custom: '" . trim($customTrim, "-") . "'<br>"; // Output: 'Hello World'
?>

Hàm xử lý chuỗi an toàn cho Unicode (mb_*)

Như đã đề cập trước đó, các hàm xử lý chuỗi cơ bản (strlen(), substr(), strpos(), strtolower(), v.v.) hoạt động dựa trên byte. Điều này có thể gây ra vấn đề với các ký tự đa byte như tiếng Việt có dấu, tiếng Nhật, tiếng Trung, v.v., vì một ký tự có thể chiếm 2, 3 hoặc 4 byte.

Để giải quyết vấn đề này, PHP cung cấp một bộ các hàm MultiByte String (mb_*) khi bạn kích hoạt mb_string extension trong php.ini. Đây là một extension cực kỳ quan trọng khi bạn làm việc với các ngôn ngữ không phải tiếng Anh.

Tầm quan trọng của mb_string extension cho UTF-8 (tiếng Việt):

  • Đảm bảo các thao tác như tính độ dài, cắt chuỗi, tìm kiếm, chuyển đổi chữ hoa/thường hoạt động chính xác trên từng ký tự thực tế, thay vì từng byte.
  • Bạn nên luôn chỉ định encoding là 'UTF-8' khi sử dụng các hàm mb_* để đảm bảo kết quả chính xác.

Các hàm mb_* phổ biến:

  • mb_strlen(): Trả về số ký tự.
  • mb_substr(): Trích xuất chuỗi con theo số ký tự.
  • mb_strpos(): Tìm vị trí chuỗi con theo số ký tự.
  • mb_strtolower(), mb_strtoupper(): Chuyển đổi chữ thường/hoa an toàn cho Unicode.
  • mb_convert_case(): Chuyển đổi chữ hoa/thường theo các quy tắc cụ thể của Unicode.

Ví dụ Code:

<?php
echo "<h3>3. Hàm xử lý chuỗi an toàn cho Unicode (mb_*):</h3>";
$vietnameseSentence = "Chào mừng bạn đến với PHP.";
$encoding = 'UTF-8'; // Luôn chỉ định encoding

// Độ dài
echo "strlen() của tiếng Việt: " . strlen($vietnameseSentence) . " bytes<br>"; // Sẽ không bằng số ký tự
echo "mb_strlen() của tiếng Việt: " . mb_strlen($vietnameseSentence, $encoding) . " ký tự<br>";

// Cắt chuỗi
echo "substr(0, 5) của tiếng Việt: " . substr($vietnameseSentence, 0, 5) . "<br>"; // Có thể cắt giữa ký tự
echo "mb_substr(0, 5) của tiếng Việt: " . mb_substr($vietnameseSentence, 0, 5, $encoding) . "<br>"; // Cắt đúng 5 ký tự: "Chào "

// Chuyển đổi chữ hoa/thường
echo "strtolower() của tiếng Việt: " . strtolower($vietnameseSentence) . "<br>"; // Có thể không chuẩn xác với dấu
echo "mb_strtolower() của tiếng Việt: " . mb_strtolower($vietnameseSentence, $encoding) . "<br>"; // Chuẩn xác hơn
?>
  • Để đảm bảo các hàm mb_* hoạt động, bạn cần kiểm tra trong php.ini xem extension=mbstring đã được bỏ ghi chú (uncomment) hay chưa và khởi động lại web server.

Hàm liên quan đến HTML và URL

Các hàm này cực kỳ quan trọng khi bạn xử lý dữ liệu web, đặc biệt là khi hiển thị nội dung ra trình duyệt hoặc khi làm việc với URL.

htmlspecialchars(string $string, int $flags = ENT_COMPAT, string $encoding = 'UTF-8', bool $double_encode = true): string:

  • Mục đích chính: Chuyển đổi các ký tự đặc biệt trong HTML (&, ", ', <, >) thành các thực thể HTML tương ứng.
  • Tầm quan trọng: Ngăn chặn các cuộc tấn công Cross-Site Scripting (XSS) bằng cách đảm bảo rằng mã HTML hoặc JavaScript độc hại do người dùng nhập vào sẽ được hiển thị dưới dạng văn bản thuần túy chứ không phải được thực thi bởi trình duyệt.
  • ENT_QUOTES: Cờ này đặc biệt hữu ích để chuyển đổi cả dấu nháy đơn (') và nháy kép (").
  • Luôn chỉ định UTF-8 cho encoding.

html_entity_decode(string $string, int $flags = ENT_COMPAT, string $encoding = 'UTF-8'): string:

  • Ngược lại với htmlspecialchars(), hàm này chuyển đổi các thực thể HTML (ví dụ: &lt; thành <) trở lại thành ký tự ban đầu của chúng.
  • Hữu ích khi bạn nhận dữ liệu đã được mã hóa HTML và muốn xử lý chúng dưới dạng văn bản thuần túy.

urlencode(string $string): string:

  • Mã hóa một chuỗi để nó có thể được sử dụng an toàn trong phần truy vấn (query string) của một URL. Nó chuyển đổi các ký tự không an toàn (như dấu cách, ký tự đặc biệt) thành các mã %XX.

urldecode(string $string): string:

  • Giải mã một chuỗi đã được mã hóa URL, chuyển đổi các mã %XX trở lại ký tự ban đầu.

Ví dụ Code:

<?php
echo "<h3>4. Hàm liên quan đến HTML và URL:</h3>";

// htmlspecialchars()
$userInput = "<script>alert('Bạn đã bị hack!');</script><b>Rất nguy hiểm!</b>";
echo "Dữ liệu người dùng (chưa thoát): " . $userInput . "<br>";
echo "Dữ liệu người dùng (đã thoát): " . htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8') . "<br>";
// Output của dòng trên sẽ hiển thị <script>alert('Bạn đã bị hack!');</script><b>Rất nguy hiểm!</b>
// thay vì chạy mã JS.

echo "<br>";

// html_entity_decode()
$encodedHtml = "&lt;p&gt;Đây là đoạn văn bản đã được &amp;quot;mã hóa&amp;quot;.&lt;/p&gt;";
echo "Chuỗi HTML đã mã hóa: " . $encodedHtml . "<br>";
echo "Sau khi giải mã: " . html_entity_decode($encodedHtml, ENT_QUOTES, 'UTF-8') . "<br>"; // Output: <p>Đây là đoạn văn bản đã được "mã hóa".</p>

echo "<br>";

// urlencode() và urldecode()
$originalUrlParam = "tên sản phẩm có dấu và khoảng trắng";
$encodedUrlParam = urlencode($originalUrlParam);
echo "Chuỗi gốc cho URL: " . $originalUrlParam . "<br>";
echo "Sau khi mã hóa URL: " . $encodedUrlParam . "<br>";
// Output: t%C3%AAn+s%E1%BA%A3n+ph%E1%BA%A9m+c%C3%B3+d%E1%BA%A5u+v%C3%A0+kho%E1%BA%A3ng+tr%E1%BA%AFng

$decodedUrlParam = urldecode($encodedUrlParam);
echo "Sau khi giải mã URL: " . $decodedUrlParam . "<br>"; // Output: tên sản phẩm có dấu và khoảng trắng
?>

Kết bài

Qua bài viết này, chúng ta đã cùng nhau khám phá sâu rộng về dữ liệu chuỗi (String) trong PHP – một kiểu dữ liệu không thể thiếu trong bất kỳ ứng dụng web nào. Bạn đã hiểu rõ chuỗi là gì, tầm quan trọng của nó, cũng như bốn cách khai báo chuỗi đa dạng mà PHP cung cấp (', ", Heredoc, Nowdoc) để phù hợp với từng nhu cầu cụ thể.

Chúng ta cũng đã đi sâu vào các phép toán và thao tác cơ bản như nối chuỗi (.), kiểm tra độ dài (strlen(), mb_strlen()), truy cập ký tự, và các phương pháp so sánh chuỗi (==, ===, strcmp(), strcasecmp()). Đặc biệt, việc làm quen với kho tàng hàm xử lý chuỗi phong phú của PHP từ tìm kiếm, thay thế, cắt ghép đến chuyển đổi định dạng, và các hàm chuyên biệt cho HTML/URL sẽ giúp bạn xử lý mọi tác vụ liên quan đến văn bản một cách hiệu quả.

Bài viết liên quan