Bài 8. Hàm

Hàm gói một đoạn mã có tên để dùng lại và tổ chức chương trình theo mô-đun. Bài này học khai báo hàm, tham số mặc định, truyền theo tên, khai báo kiểu, tham chiếu, hàm biến đổi (variadic), hàm ẩn danh, arrow function và các hàm có sẵn thường dùng.

50 phútCơ bản
Bạn sẽ học được
  • Khai báo và gọi hàm có tham số, giá trị trả về
  • Dùng tham số mặc định, truyền theo tên, khai báo kiểu, strict_types
  • Hiểu phạm vi biến, tham chiếu, static
  • Viết closure, arrow function; dùng hàm có sẵn
Thuật ngữ cần biết
Tham số (parameter)
Biến nhận giá trị khi hàm được gọi.
Giá trị trả về
Kết quả hàm đưa ra qua return.
Khai báo kiểu
Ghi kiểu cho tham số và kết quả: int, string, ?array...
Closure
Hàm ẩn danh, có thể “mang theo” biến bên ngoài bằng use.

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

Nguyên tắc: mỗi hàm làm một việc, tên là động từ (tinh_diem_tb, kiem_tra_email), dưới 30 dòng. Hàm nên trả về kết quả thay vì echo trực tiếp, để nơi gọi quyết định hiển thị. Hàm có phạm vi riêng: không thấy biến bên ngoài trừ khi truyền vào.

Khai báo hàm

<?php
declare(strict_types=1);

function tinh_diem_tb(array $diem): float {
    if (count($diem) === 0) return 0.0;
    return round(array_sum($diem) / count($diem), 2);
}
function xep_loai(float $diem, float $nguong_gioi = 8.5): string {
    return $diem >= $nguong_gioi ? "Giỏi" : ($diem >= 5 ? "Đạt" : "Không đạt");
}
echo tinh_diem_tb([8, 9, 7.5]);           // 8.17
echo xep_loai(8.6);                        // Giỏi (dùng mặc định)
echo xep_loai(nguong_gioi: 9, diem: 8.6);  // truyền theo tên (PHP 8)
function tim(string $ma): ?array { return null; }   // ?array: có thể null
function ghi_log(string $m): void { error_log($m); } // không trả về

Tham chiếu, static, variadic

<?php
function tang(int &$so): void { $so++; }   // & : sửa biến gốc
$a = 5; tang($a); echo $a;                   // 6

function dem_luot(): int {
    static $dem = 0;    // giữ giá trị giữa các lần gọi
    return ++$dem;
}
dem_luot(); dem_luot(); echo dem_luot();     // 3

function tong(int ...$so): int { return array_sum($so); }  // nhận nhiều đối số
echo tong(1, 2, 3, 4);                        // 10
$ds = [5, 6]; echo tong(...$ds);              // 11 (trải mảng)

Hàm ẩn danh và arrow function

<?php
$he_so = 1.2;
$nhan = function (float $x) use ($he_so): float { return $x * $he_so; };
echo $nhan(10);                                // 12
$binh_phuong = fn($x) => $x * $x;              // arrow fn: tự thấy biến ngoài
$ds = [1, 2, 3, 4];
print_r(array_map(fn($x) => $x * $x, $ds));           // [1,4,9,16]
print_r(array_filter($ds, fn($x) => $x % 2 == 0));    // [2,4]
usort($sv, fn($a, $b) => $b["diem"] <=> $a["diem"]);  // sắp xếp giảm dần

Hàm có sẵn thường dùng

NhómHàm
Chuỗistrlen, mb_strlen, strtoupper, mb_strtoupper, trim, str_replace, substr, mb_substr, strpos, explode, implode, sprintf, str_contains, str_starts_with
Sốabs, round, floor, ceil, max, min, rand, random_int, number_format
Mảngcount, array_push, array_pop, in_array, array_keys, array_merge, sort, usort, array_map, array_filter, array_sum
Kiểm traisset, empty, is_numeric, filter_var
Khácdate, time, json_encode, json_decode, var_dump, print_r

Tra cứu tại php.net/manual/vi với ví dụ cho từng hàm.

Mẹo hay

Tách các hàm dùng chung vào tệp functions.php và require_once ở đầu mỗi trang (bài Include).

Lưu ý

Khi bật strict_types=1, gọi xep_loai("8") với chuỗi sẽ báo TypeError thay vì tự chuyển: đây là điều mong muốn để bắt lỗi sớm.

Thực hành
  1. Viết hàm kiem_tra_email(string): bool dùng filter_var.
  2. Viết hàm dinh_dang_tien(int|float): string trả về dạng 1.250.000 đ.
  3. Viết hàm giai_thua đệ quy và hàm fibonacci dùng static để nhớ kết quả.
  4. Dùng array_map và arrow function chuyển mảng tên thành chữ hoa đầu từ (mb_convert_case).
Tóm tắt bài học
  • function ten(kiểu $tham_so): kiểu_trả_về.
  • Mặc định, truyền theo tên, ?kiểu, void, variadic.
  • & tham chiếu; static nhớ giá trị; closure dùng use; fn => ngắn gọn.
  • Tận dụng hàm có sẵn, tra php.net.