Sau khi nắm vững vòng lặp trong PHP, bước tiếp theo là học cách tổ chức code hiệu quả với hàm trong PHP. Hàm giúp bạn gom nhóm các đoạn code thực hiện một nhiệm vụ cụ thể, tránh lặp lại code và làm chương trình dễ đọc, dễ bảo trì hơn. Thay vì viết cùng một đoạn code 10 lần ở 10 nơi khác nhau, bạn chỉ cần tạo 1 hàm và gọi nó 10 lần.
1. Hàm là gì?
Hàm (Function) là một khối code có tên, thực hiện một nhiệm vụ cụ thể. Bạn có thể gọi hàm nhiều lần mà không cần viết lại code. Ví dụ thực tế:
- ✅ Hàm tính tổng 2 số
- ✅ Hàm kiểm tra email hợp lệ
- ✅ Hàm kết nối database
- ✅ Hàm gửi email
- ✅ Hàm format tiền tệ
PHP có 2 loại hàm:
- ✅ Hàm built-in: PHP cung cấp sẵn (
strlen(),array_push(),date()…) - ✅ Hàm tự định nghĩa: Lập trình viên tự tạo theo nhu cầu
2. Cú pháp tạo hàm
<?php
// Cú pháp cơ bản
function ten_ham() {
// Code thực thi
}
// Ví dụ 1: Hàm đơn giản
function chao() {
echo "Xin chào!";
}
// Gọi hàm
chao(); // Kết quả: Xin chào!
chao(); // Kết quả: Xin chào!
// Ví dụ 2: Hàm in dấu sao
function inDauSao() {
echo "*****<br>";
}
inDauSao();
inDauSao();
inDauSao();
/*
Kết quả:
*****
*****
*****
*/
?>2.1. Quy tắc đặt tên hàm
<?php
// ✅ Đúng
function tinhTong() { }
function tinh_tong() { }
function TinhTong() { }
function _private() { }
// ❌ Sai
function 123ham() { } // Bắt đầu bằng số
function tinh-tong() { } // Có dấu gạch ngang
function tinh tong() { } // Có khoảng trắng
// Lưu ý: PHP không phân biệt hoa thường tên hàm
function chaoMung() { }
ChaoMung(); // Vẫn chạy được
?>💡 Quy ước đặt tên:
– Dùng động từ:tinhTong(),guiEmail(),kiemTraTuoi()
– Rõ ràng, mô tả đúng nhiệm vụ
– Dùng camelCase hoặc snake_case nhất quán
3. Hàm có tham số (Parameters)
Tham số cho phép truyền dữ liệu vào hàm để xử lý:
<?php
// Cú pháp
function ten_ham($tham_so_1, $tham_so_2) {
// Code sử dụng tham số
}
// Ví dụ 1: Hàm tính tổng 2 số
function tinhTong($a, $b) {
$tong = $a + $b;
echo "Tổng: $tong";
}
tinhTong(10, 20); // Tổng: 30
tinhTong(5, 7); // Tổng: 12
// Ví dụ 2: Hàm chào theo tên
function chao($ten) {
echo "Xin chào, $ten!<br>";
}
chao("Nguyễn Văn A"); // Xin chào, Nguyễn Văn A!
chao("Trần Thị B"); // Xin chào, Trần Thị B!
?>3.1. Tham số mặc định (Default Parameters)
<?php
// Tham số có giá trị mặc định
function chao($ten = "Khách") {
echo "Xin chào, $ten!<br>";
}
chao("An"); // Xin chào, An!
chao(); // Xin chào, Khách! (dùng giá trị mặc định)
// Ví dụ 2: Tính lũy thừa
function luyThua($co_so, $so_mu = 2) {
return pow($co_so, $so_mu);
}
echo luyThua(5); // 25 (5^2)
echo luyThua(5, 3); // 125 (5^3)
?>3.2. Số lượng tham số linh hoạt
<?php
// Dùng func_get_args() để nhận mảng tham số
function tinhTongNhieuSo() {
$args = func_get_args();
$tong = 0;
foreach ($args as $so) {
$tong += $so;
}
return $tong;
}
echo tinhTongNhieuSo(1, 2, 3); // 6
echo tinhTongNhieuSo(10, 20, 30, 40); // 100
// PHP 5.6+: Dùng toán tử ... (spread operator)
function tinhTong(...$so) {
return array_sum($so);
}
echo tinhTong(5, 10, 15, 20); // 50
?>4. Hàm trả về giá trị (Return)
Dùng return để hàm trả về kết quả thay vì chỉ in ra:
<?php
// Không return - chỉ in ra
function tinhTong1($a, $b) {
echo $a + $b;
}
// Có return - trả về giá trị
function tinhTong2($a, $b) {
return $a + $b;
}
// So sánh
tinhTong1(5, 3); // In ra: 8 (không lưu được)
$ket_qua = tinhTong2(5, 3); // Lưu vào biến
echo $ket_qua; // 8
echo $ket_qua * 2; // 16 (có thể tính toán tiếp)
?>4.1. Ví dụ thực tế
<?php
// Hàm kiểm tra số chẵn
function laSoChan($so) {
if ($so % 2 == 0) {
return true;
} else {
return false;
}
}
// Hoặc ngắn gọn hơn
function laSoChan2($so) {
return $so % 2 == 0;
}
if (laSoChan(10)) {
echo "10 là số chẵn";
}
// Hàm tính điểm trung bình
function tinhDiemTB($diem_toan, $diem_ly, $diem_hoa) {
return ($diem_toan + $diem_ly + $diem_hoa) / 3;
}
$dtb = tinhDiemTB(8, 7, 9);
echo "Điểm TB: " . number_format($dtb, 2); // 8.00
?>4.2. Return sớm (Early Return)
<?php
function kiemTraTuoi($tuoi) {
// Return sớm nếu điều kiện không hợp lệ
if ($tuoi < 0) {
return "Tuổi không hợp lệ";
}
if ($tuoi < 18) {
return "Vị thành niên";
}
if ($tuoi < 60) {
return "Trưởng thành";
}
return "Cao tuổi";
}
echo kiemTraTuoi(-5); // Tuổi không hợp lệ
echo kiemTraTuoi(15); // Vị thành niên
echo kiemTraTuoi(30); // Trưởng thành
echo kiemTraTuoi(65); // Cao tuổi
?>5. Phạm vi biến (Variable Scope)
Biến trong hàm có phạm vi riêng, khác với biến bên ngoài:
<?php
$x = 10; // Biến toàn cục
function testScope() {
$y = 20; // Biến cục bộ
// ❌ Không truy cập được $x
// echo $x; // Lỗi: Undefined variable
echo $y; // 20 - OK
}
testScope();
// ❌ Không truy cập được $y
// echo $y; // Lỗi: Undefined variable
?>5.1. Sử dụng biến toàn cục trong hàm
<?php
$bien_toan_cuc = 100;
// Cách 1: Dùng từ khóa global
function ham1() {
global $bien_toan_cuc;
echo $bien_toan_cuc; // 100
}
// Cách 2: Dùng $GLOBALS
function ham2() {
echo $GLOBALS['bien_toan_cuc']; // 100
}
ham1();
ham2();
?>5.2. Biến tĩnh (Static Variables)
<?php
function demSo() {
static $dem = 0; // Giữ giá trị giữa các lần gọi
$dem++;
echo "Đã gọi $dem lần<br>";
}
demSo(); // Đã gọi 1 lần
demSo(); // Đã gọi 2 lần
demSo(); // Đã gọi 3 lần
// So sánh với biến thường
function demSo2() {
$dem = 0; // Reset về 0 mỗi lần gọi
$dem++;
echo "Đã gọi $dem lần<br>";
}
demSo2(); // Đã gọi 1 lần
demSo2(); // Đã gọi 1 lần (không tăng)
?>6. Tham chiếu (Pass by Reference)
Mặc định PHP truyền tham số theo giá trị (copy). Dùng & để truyền theo tham chiếu:
<?php
// Truyền theo giá trị (mặc định)
function tangGiaTri($so) {
$so++;
}
$x = 10;
tangGiaTri($x);
echo $x; // 10 (không đổi)
// Truyền theo tham chiếu
function tangThamChieu(&$so) {
$so++;
}
$y = 10;
tangThamChieu($y);
echo $y; // 11 (đã thay đổi)
// Ví dụ thực tế: Swap 2 số
function hoanDoi(&$a, &$b) {
$temp = $a;
$a = $b;
$b = $temp;
}
$x = 5;
$y = 10;
echo "Trước: x=$x, y=$y<br>";
hoanDoi($x, $y);
echo "Sau: x=$x, y=$y"; // x=10, y=5
?>7. Type Hinting và Return Type
PHP 7+ hỗ trợ khai báo kiểu dữ liệu cho tham số và giá trị trả về:
<?php
// Type hinting cho tham số
function tinhTong(int $a, int $b) {
return $a + $b;
}
echo tinhTong(5, 10); // 15
echo tinhTong(5.5, 10.2); // 15 (tự động ép kiểu thành int)
// Return type
function layTen(): string {
return "Nguyễn Văn A";
}
function laSoChan(int $so): bool {
return $so % 2 == 0;
}
// Nullable type (PHP 7.1+)
function timSinhVien(int $id): ?array {
// Trả về array hoặc null
if ($id > 0) {
return ["id" => $id, "ten" => "SV $id"];
}
return null;
}
var_dump(timSinhVien(5)); // array
var_dump(timSinhVien(-1)); // null
?>8. Hàm đệ quy (Recursive Function)
Hàm gọi chính nó để giải quyết bài toán:
<?php
// Ví dụ 1: Tính giai thừa
function giaiThua($n) {
if ($n <= 1) {
return 1; // Điểm dừng
}
return $n * giaiThua($n - 1);
}
echo giaiThua(5); // 120 (5 * 4 * 3 * 2 * 1)
/*
Giải thích:
giaiThua(5) = 5 * giaiThua(4)
= 5 * 4 * giaiThua(3)
= 5 * 4 * 3 * giaiThua(2)
= 5 * 4 * 3 * 2 * giaiThua(1)
= 5 * 4 * 3 * 2 * 1
= 120
*/
// Ví dụ 2: Dãy Fibonacci
function fibonacci($n) {
if ($n <= 1) {
return $n;
}
return fibonacci($n - 1) + fibonacci($n - 2);
}
// In 10 số Fibonacci đầu tiên
for ($i = 0; $i < 10; $i++) {
echo fibonacci($i) . " ";
}
// Kết quả: 0 1 1 2 3 5 8 13 21 34
?>⚠️ Lưu ý: Hàm đệ quy phải có điểm dừng (base case), nếu không sẽ gây lỗi tràn bộ nhớ (stack overflow).
9. Hàm ẩn danh (Anonymous Function)
Hàm không có tên, thường dùng làm callback:
<?php
// Gán hàm ẩn danh vào biến
$chao = function($ten) {
echo "Xin chào, $ten!";
};
$chao("An"); // Xin chào, An!
// Dùng làm callback
$mang = [1, 2, 3, 4, 5];
$mang_binh_phuong = array_map(function($so) {
return $so * $so;
}, $mang);
print_r($mang_binh_phuong); // [1, 4, 9, 16, 25]
// Lọc số chẵn
$so_chan = array_filter($mang, function($so) {
return $so % 2 == 0;
});
print_r($so_chan); // [2, 4]
?>9.1. Arrow Function (PHP 7.4+)
<?php
// Cú pháp ngắn gọn hơn
$mang = [1, 2, 3, 4, 5];
// Arrow function
$binh_phuong = array_map(fn($x) => $x * $x, $mang);
print_r($binh_phuong); // [1, 4, 9, 16, 25]
// So sánh
$tong = 10;
// Anonymous function: Cần 'use'
$cong1 = function($x) use ($tong) {
return $x + $tong;
};
// Arrow function: Tự động access biến ngoài
$cong2 = fn($x) => $x + $tong;
echo $cong1(5); // 15
echo $cong2(5); // 15
?>10. Một số hàm built-in hữu ích
10.1. Hàm xử lý chuỗi
<?php
$text = "Lập Trình Không Khó";
echo strlen($text); // 22 (độ dài)
echo strtoupper($text); // LẬP TRÌNH KHÔNG KHÓ
echo strtolower($text); // lập trình không khó
echo str_replace("Khó", "Dễ", $text); // Lập Trình Không Dễ
$email = " test@email.com ";
echo trim($email); // test@email.com (xóa khoảng trắng)
?>10.2. Hàm xử lý mảng
<?php
$mang = [3, 1, 4, 1, 5, 9];
echo count($mang); // 6
echo max($mang); // 9
echo min($mang); // 1
echo array_sum($mang); // 23
sort($mang); // Sắp xếp tăng dần
print_r($mang); // [1, 1, 3, 4, 5, 9]
$mang2 = [1, 2, 3];
array_push($mang2, 4, 5); // Thêm vào cuối
print_r($mang2); // [1, 2, 3, 4, 5]
?>10.3. Hàm xử lý ngày tháng
<?php
echo date("d/m/Y"); // 06/05/2026
echo date("H:i:s"); // 14:30:45
echo date("l, d F Y"); // Wednesday, 06 May 2026
$timestamp = strtotime("2026-12-31");
echo date("d/m/Y", $timestamp); // 31/12/2026
// Tính số ngày giữa 2 ngày
$ngay1 = strtotime("2026-01-01");
$ngay2 = strtotime("2026-12-31");
$so_ngay = ($ngay2 - $ngay1) / (60 * 60 * 24);
echo "Số ngày: $so_ngay"; // 364
?>11. Ví dụ tổng hợp
11.1. Hệ thống xác thực đơn giản
<?php
function kiemTraEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
function kiemTraMatKhau($mat_khau) {
// Ít nhất 8 ký tự, có chữ và số
if (strlen($mat_khau) < 8) {
return false;
}
if (!preg_match('/[a-zA-Z]/', $mat_khau)) {
return false;
}
if (!preg_match('/[0-9]/', $mat_khau)) {
return false;
}
return true;
}
function dangKy($email, $mat_khau) {
if (!kiemTraEmail($email)) {
return "Email không hợp lệ";
}
if (!kiemTraMatKhau($mat_khau)) {
return "Mật khẩu phải có ít nhất 8 ký tự, gồm chữ và số";
}
// Lưu vào database (giả lập)
return "Đăng ký thành công!";
}
echo dangKy("test@email.com", "pass123");
?>11.2. Tính toán hóa đơn
<?php
function tinhThue($tien, $thue_suat = 10) {
return $tien * ($thue_suat / 100);
}
function tinhGiamGia($tien, $ma_giam_gia = "") {
$muc_giam = [
"SALE10" => 10,
"SALE20" => 20,
"VIP30" => 30
];
if (isset($muc_giam[$ma_giam_gia])) {
return $tien * ($muc_giam[$ma_giam_gia] / 100);
}
return 0;
}
function tinhTongHoaDon($tien_hang, $ma_giam_gia = "") {
$giam_gia = tinhGiamGia($tien_hang, $ma_giam_gia);
$sau_giam = $tien_hang - $giam_gia;
$thue = tinhThue($sau_giam);
$tong = $sau_giam + $thue;
return [
"tien_hang" => $tien_hang,
"giam_gia" => $giam_gia,
"sau_giam" => $sau_giam,
"thue" => $thue,
"tong_cong" => $tong
];
}
$hoa_don = tinhTongHoaDon(1000000, "SALE20");
echo "Tiền hàng: " . number_format($hoa_don['tien_hang']) . " VNĐ<br>";
echo "Giảm giá: " . number_format($hoa_don['giam_gia']) . " VNĐ<br>";
echo "Thuế VAT: " . number_format($hoa_don['thue']) . " VNĐ<br>";
echo "<strong>Tổng cộng: " . number_format($hoa_don['tong_cong']) . " VNĐ</strong>";
?>Tóm tắt
Qua bài này bạn đã nắm được:
- ✅ Hàm trong PHP là khối code có tên, thực hiện nhiệm vụ cụ thể, tái sử dụng được
- ✅ Cú pháp:
function ten_ham($tham_so) { ... } - ✅ Tham số: Truyền dữ liệu vào hàm, có thể có giá trị mặc định
- ✅ Return: Trả về kết quả từ hàm, dùng
return $gia_tri; - ✅ Scope: Biến trong hàm là cục bộ, dùng
globalđể truy cập biến toàn cục - ✅ Tham chiếu: Dùng
&để truyền tham số theo tham chiếu - ✅ Type hinting: Khai báo kiểu dữ liệu tham số và return type (PHP 7+)
- ✅ Hàm đệ quy: Hàm gọi chính nó, cần có điểm dừng
- ✅ Anonymous function: Hàm không tên, dùng làm callback
- ✅ Arrow function: Cú pháp ngắn gọn
fn($x) => $x * 2(PHP 7.4+)
Bài tiếp theo, bạn sẽ học về mảng trong PHP để lưu trữ và xử lý nhiều dữ liệu cùng lúc.
🎯 Bài tập thực hành
- Bài 1: Viết hàm
laSoNguyenTo($n)kiểm tra số nguyên tố. Hàm trả vềtruenếu là số nguyên tố,falsenếu không. - Bài 2: Viết hàm
formatTien($so)format số thành dạng tiền tệ VNĐ. VD:formatTien(1500000)→ "1,500,000 VNĐ" - Bài 3: Viết hàm
tinhDiemTB($diem_array)nhận mảng điểm, trả về:- Điểm trung bình
- Điểm cao nhất
- Điểm thấp nhất
Gợi ý Bài 1:
<?php
function laSoNguyenTo($n) {
if ($n < 2) {
return false;
}
for ($i = 2; $i <= sqrt($n); $i++) {
if ($n % $i == 0) {
return false;
}
}
return true;
}
// Test
var_dump(laSoNguyenTo(7)); // true
var_dump(laSoNguyenTo(10)); // false
var_dump(laSoNguyenTo(13)); // true
?>Gợi ý Bài 2:
<?php
function formatTien($so) {
return number_format($so, 0, ',', '.') . " VNĐ";
}
echo formatTien(1500000); // 1,500,000 VNĐ
echo formatTien(250000); // 250,000 VNĐ
?>Gợi ý Bài 3:
<?php
function tinhDiemTB($diem_array) {
if (empty($diem_array)) {
return null;
}
$trung_binh = array_sum($diem_array) / count($diem_array);
$cao_nhat = max($diem_array);
$thap_nhat = min($diem_array);
return [
"trung_binh" => round($trung_binh, 2),
"cao_nhat" => $cao_nhat,
"thap_nhat" => $thap_nhat
];
}
$diem = [7.5, 8.0, 6.5, 9.0, 8.5];
$ket_qua = tinhDiemTB($diem);
echo "Điểm TB: " . $ket_qua['trung_binh'] . "<br>";
echo "Cao nhất: " . $ket_qua['cao_nhat'] . "<br>";
echo "Thấp nhất: " . $ket_qua['thap_nhat'];
?>