Điều khiển rẽ nhánh trong PHP: if-elseif-else, switch-case

    0

    Ngôn ngữ PHP cung cấp hai lệnh điều khiển rẽ nhánh: if-elseif-else và switch-case, cùng với một phép toán rẽ nhánh, gọi là phép toán điều kiện. Các lệnh điều khiển rẽ nhánh chỉ là hai trong số rất nhiều lệnh điều khiển khác của PHP.

    Giới thiệu chung về lệnh điều khiển trong PHP

    Trong tất cả các ví dụ thực hiện từ đầu đến giờ, code đều thực hiện theo trật tự tuyến tính: lệnh nào viết trước sẽ thực hiện trước.

    Thực hiện code theo trật tự tuyến tính là không đủ để xây dựng các script với logic phức tạp. Ví dụ, trong nhiều trường hợp chúng ta muốn thực hiện lệnh nếu đạt một điều kiện nhất định, hoặc lặp lại thực hiện một nhóm lệnh.

    Để thực hiện các logic phức tạp, PHP, giống như nhiều ngôn ngữ lập trình imperative khác, cung cấp các mệnh lệnh điều khiển (flow-control statements).

    Lệnh điều khiển thay đổi trật tự thực thi code thông thường và giúp thực thi những ý tưởng phức tạp hơn của người lập trình.

    PHP có các lệnh điều khiển sau:

    • Điều khiển rẽ nhánh if.
    • Điều khiển rẽ nhiều nhánh switch.
    • Điều khiển lặp while.
    • Điều khiển lặp do .. while.
    • Điều khiển lặp for.
    • Điều khiển lặp foreach.
    • Điều khiển thoát exit và return.
    • Điểu khiển nhảy vô điều kiện goto.
    • Điều khiển kiểm soát ngoại lệ try .. catch.

    Các lệnh điều khiển đều thuộc nhóm mệnh lệnh (statement). Chúng đồng thời còn là những mệnh lệnh phức tạp do chúng có thể chứa nhiều lệnh bên trong.

    Các lệnh điều khiển rẽ nhánh if và switch sẽ được trình bày trong bài học này. Các lệnh điều khiển lặp sẽ học trong bài tiếp theo. Điều khiển thoát sẽ học trong bài về hàm. Điều khiển kiểm soát ngoại lệ sẽ học riêng trong bài học về ngoại lệ.

    Riêng lệnh nhảy goto không được khuyến khích sử dụng do nó phá vỡ tính cấu trúc của code. Vì vậy chúng ta sẽ không xem xét lệnh này.

    Lệnh rẽ nhánh if trong PHP

    Hãy xem ví dụ sau đây:

    <?php
    $name = readline('Your name: ');
    if (stripos($name, 'trump')) {
        echo 'Hello, Mr. president! Welcome to heaven!';
    } else {
        echo "Hello, $name. Welcome to hell!";
    }

    Trong ví dụ trên chúng ta sử dụng hàm stripos($haystack, $needle, $offset = null) false|int. Hàm này trả về vị trí cuối cùng mà xâu con $needle xuất hiện trong xâu lớn $haystack. Nếu không tìm thấy xâu con, hàm sẽ trả lại false.

    Chúng ta vận dụng hàm stripos() để kiểm tra tên người dùng nhập vào: nếu chứa cụm ‘trump’ thì in lời chào đặc biệt; ngược lại sẽ phát lời chào thông thường. Tức là, lệnh thực hiện sẽ phụ thuộc vào việc tên gọi có chứa cụm ‘trump’ hay không.

    Kết quả chạy chương trình với hai dữ liệu khác nhau:

    C:\TuHocICT\LearnPHP\Controls>php if-else.php
    Your name: Donald Trump
    Hello, Mr. president! Welcome to heaven!
    C:\TuHocICT\LearnPHP\Controls>php if-else.php
    Your name: Obama
    Hello, Obama. Welcome to hell!

    Nếu quen thuộc với C, bạn sẽ thấy cấu trúc này hoàn toàn tương tự:

    if(biểu_thức) lệnh
    else lệnh
    
    hoặc
    
    if(biểu_thức){
      lệnh 1;
      lệnh 2;
      ...
    }
    else {
      lệnh 1;
      lệnh 2;
      ...
    }

    Trong đó:

    • Biểu thức phải quy đổi được về giá trị boolean. Thực tế, PHP có thể tự động chuyển đổi các giá trị khác về kiểu boolean. Ví dụ, 0 về false, chuỗi rỗng về false, v.v..
    • Biểu thức phải đặt trong cặp dấu ngoặc tròn (). Thiếu cặp dấu ngoặc tròn sẽ dẫn đến lỗi cú pháp.
    • Nếu sau if có nhiều lệnh thì chúng phải đặt trong cặp dấu {}. Những lệnh nằm trong cặp {} tạo thành một khối code (code block). Nếu sau if chỉ có một lệnh thì không cần cặp {}.

    Trong ví dụ này bạn cũng đã thấy sau khối code của lệnh if còn có từ khóa else và một khối code nữa. Khối code và từ khóa else này là một mệnh đề (clause) khác của lệnh if.

    Nếu sử dụng sơ đồ khối (flow chart), lệnh if-else được biểu diễn như sau:

    Ở đây luồng thực thi bị phân làm hai, và chỉ thực hiện theo một trong hai đường, nên lệnh if-else còn được gọi là lệnh rẽ nhánh.

    Như đã nói, khi biểu thức của if tính ra giá trị true thì thực hiện khối code của if. Trong trường hợp còn lại (biểu thức của if tính ra false) thì sẽ thực hiện khối code của else.

    Các lệnh if-else lồng nhau, elseif

    Do if-else cũng chỉ là các lệnh, bạn có thể lồng các lệnh if-else với nhau nếu cần diễn đạt những logic phức tạp hơn. Ví dụ:

    <?php
    $name = readline('Your name: ');
    $name_lower = strtolower($name);
    if ($name_lower == 'trump') {
        $greeting = 'Mr. president!';
    } else {
        if ($name_lower == 'obama')
            $greeting = 'Mr. Obama. Great to see you!';
        else {
            if ($name_lower == 'bush')
                $greeting = 'Mr. Bush - man of wars';
            else {
                if ($name_lower == 'clinton')
                    $greeting = 'Mr. Clinton, how is Monica!';
                else
                    $greeting = 'Welcome to PHP';
            }
        }
    }
    echo $greeting;

    Trong ví dụ này, tùy thuộc vào tên người nhập chúng ta sẽ đưa ra lời chào khác nhau. Ví dụ, tên trump sẽ nhận được lời chào ‘Mr. presidents!’, tên obama sẽ nhận được lời chào ‘Mr. Obama. Great to see you!’. Nếu nhập một tên ngoài những tên đã xác định trước (trump, obama, bush, clinton) thì lời chào chung là ‘Welcome to PHP’.

    Rất dễ thấy là việc lồng các lệnh if – else như trên rất khó đọc!

    Bạn có thể viết lại script trên như sau:

    $name = readline('Your name: ');
    $name_lower = strtolower($name);
    if ($name_lower == 'trump')
        $greeting = 'Mr. president!';
    elseif ($name_lower == 'obama')
        $greeting = 'Mr. Obama. Great to see you!';
    elseif ($name_lower == 'bush')
        $greeting = 'Mr. Bush - man of wars';
    elseif ($name_lower == 'clinton')
        $greeting = 'Mr. Clinton, how is Monica!';
    else
        $greeting = 'Welcome to PHP';
    echo $greeting;

    Ở đây chúng ta vận dụng một mệnh đề đặc biệt của lệnh if-else: mệnh đề elseif.

    Về mặt ý nghĩa nó giống hệt như cách bạn lồng một lệnh if mới trong mệnh đề else của lệnh if bên ngoài. Tuy nhiên, mệnh đề elseif giúp code dễ đọc dễ theo dõi hơn nhiều.

    Nếu sử dụng sơ đồ khối bạn có thể biểu diễn lệnh if-elseif-else như sau:

    Một cách khác tốt hơn để giải quyết những tình huống tương tự là sử dụng lệnh switch-case. Chúng ta sẽ xem xét switch-case ở phần sau của bài học.

    Cùng lấy một ví dụ khác:

    <?php
    
    $age = readline('Your age: ');
    if($age >= 18)
    	$str = 'Đại học';
    elseif($age >= 16)
    	$str = 'Trung học phổ thông';
    elseif($age >= 12)
    	$str = 'Trung học cơ sở';
    elseif($age >= 6)
    	$str = 'Tiểu học';
    elseif($age >= 2)
    	$str = 'Mẫu giáo';
    elseif($age >= 0)
    	$str = 'Sơ sinh';
    else
    	$str = 'Bạn đã ra đời chưa?';
    echo $str;

    Trong ví dụ này bạn yêu cầu nhập giá trị tuổi. Tùy vào độ tuổi sẽ đưa ra thông tin tương ứng về cấp học.

    Ở đây các mệnh elseif cho phép dễ dàng phân chia độ tuổi thành các khoảng (.. 0), [0, 2), [2, 6), [6, 12), [12, 16), [16, 18), [18 …). Nếu vẫn sử dụng các lệnh if lồng nhau sẽ rất khó theo dõi.

    Phép toán điều kiện ? : trong PHP

    Cấu trúc if-else bạn xem xét ở trên là một statement, nghĩa là nó thực hiện lệnh nhưng không trả về kết quả. Nếu bạn muốn gán giá trị cho biến tùy theo điều kiện cụ thể, bạn có thể sử dụng lệnh if-else như sau:

    $name = readline('Your name: ');
    if (stripos($name, 'trump')) {
        $greeting = 'Hello, Mr. president! Welcome to heaven!';
    } else {
        $greeting = "Hello, $name. Welcome to hell!";
    }
    echo $greeting;

    Ở đây, thay vì trực tiếp in ra bằng lệnh echo, bạn gán giá trị cho biến $greeting tùy thuộc vào giá trị $name. Cuối cùng chỉ phát ra một lệnh echo.

    Bạn có thể sử dụng phép toán điều kiện (conditional operator) để đơn giản hóa việc gán giá trị như sau:

    $name = readline('Your name: ');
    $greeting = stripos($name, 'trump') ? 'Hello, Mr. president! Welcome to heaven!' : "Hello, $name. Welcome to hell!";
    echo $greeting;

    Đoạn code dùng phép toán điều kiện và đoạn code dùng lệnh if là tương đương nhau. Chỉ là cách viết của phép toán điều kiện ngắn gọn xúc tích hơn.

    Cú pháp chung của phép toán điều kiện như sau:

    $kết_quả = biểu_thức_logic ? giá_trị_1 : giá_trị_2;

    Theo đó, nếu biểu thức logic nhận giá trị true thì biến $kết quả sẽ nhận giá trị 1, ngược lại sẽ nhận giá trị 2.

    Phép toán điều kiện là phép toán ternary (phép toán có 3 toán hạng) duy nhất trong PHP.

    Lệnh rẽ nhiều nhánh switch / case

    Khi có nhiều điều kiện khác nhau, bạn có thể lồng các lệnh for với nhau hoặc sử dụng các mệnh đề elseif như trên.

    Để đơn giản hơn nữa trong việc viết các lệnh rẽ nhiều nhánh, PHP cung cấp một lệnh đặc biệt: lệnh switch – case.

    Hãy xem ví dụ sau đây:

    <?php
    $name = readline('Your name: ');
    switch (strtolower($name)) {
        case 'trump':
            $greeting = 'Mr. president!';
            break;
        case 'obama':
            $greeting = 'Mr. Obama. Great to see you!';
            break;
        case 'bush':
            $greeting = 'Mr. Bush - man of wars';
            break;
        case 'clinton':
            $greeting = 'Mr. Clinton, how is Monica!';
            break;
        default:
            $greeting = 'Welcome to PHP';
            break;
    }
    echo $greeting;

    Trong cấu trúc này, PHP sẽ lấy biểu thức của lệnh switch và lần lượt so sánh với các hằng số của từng ‘case’. Nếu trùng khớp với hằng số của case nào thì các lệnh đi sau case đó (cho đến lệnh break tương ứng) sẽ được thực thi.

    Bạn có thể hình dung switch-case-default ở ví dụ trên giống như một hệ if-elseif-else. Trong đó, mỗi case tương đương với biểu thức so sánh bằng ở mỗi mệnh đề elseif, và phần default tương tự như mệnh đề else.

    Phần default là không bắt buộc trong cấu trúc switch – case. Nếu có mặt default và biểu thức KHÔNG so khớp được với bất kỳ case nào thì khối code của default sẽ được thực thi.

    Nếu KHÔNG có phần default và biểu thức KHÔNG so khớp được với bất kỳ case nào thì không có bất kỳ case nào được thực thi.

    Từ khóa break ở mỗi case đảm bảo rằng, nếu tìm thấy một case phù hợp (và thực thi xong phần khối code tương ứng), PHP sẽ thoát ra khỏi lệnh break mà không tiếp tục kiểm tra các case tiếp theo.

    Từ khóa break ở mỗi case là không bắt buộc. Tuy nhiên bạn nên dùng break cho mỗi case. Các IDE cũng đưa ra thông báo nếu bạn quên break ở một case.

    Điều gì xảy ra nếu bạn bỏ break?
    Nếu ở một case nào đó bạn không sử dụng break, và giá trị biểu thức so khớp với hằng của case đó, đầu tiên PHP sẽ thực hiện khối code của case này. Tuy nhiên, sau đó PHP vẫn sẽ tiếp tục đem giá trị biểu thức so khớp với hằng của case tiếp theo. Điều này thường dẫn đến thao tác so khớp dư thừa, vì switch-case thường được thiết kế để mỗi lần chạy chỉ có 1 case được thực hiện.

    Nếu bạn cần mô phỏng điều kiện ‘or’ – thực hiện khối code nếu biểu thức có giá trị 1 HOẶC giá trị 2 HOẶC giá trị 3, bạn cần sử dụng một kỹ thuật khác của switch-case.

    Hãy xem ví dụ sau:

    switch (strtolower($name)) {
        case 'trump': // fall-through        
        case 'obama':        
        case 'bush':
            $greeting = 'Mr. president!';
            break;
        case 'clinton':
            $greeting = 'Mr. Clinton, how is Monica!';
            break;
        default:
            $greeting = 'Welcome to PHP';
            break;
    }

    Trong trường hợp này, nếu $name có giá trị ‘trump’, hoặc ‘obama’, hoặc ‘bush’ sẽ đều kích hoạt chung một nhóm lệnh. Cách sử dụng case như vậy có tên gọi là fall-through (trượt qua). Khi sử dụng fall-through bạn nên viết comment bên cạnh để tránh lẫn lộn.

    Cú pháp khác của if và switch

    Cách viết khối code thân của lệnh if-else và switch-case như trên được tham khảo từ lối viết tương ứng của C. Bạn có thể tiếp tục sử dụng bình thường.

    Tuy nhiên, khi trộn lẫn code PHP với văn bản khác (như HTML), lối viết khối code với các dấu ngoặc nhọn tương đối khó theo dõi.

    PHP cung cấp một cú pháp khác để viết các cấu trúc này. Hãy xem ví dụ sau:

    $name = readline('Your name: ');
    if(stripos($name, 'trump')):
        echo 'Hello, Mr. president! Welcome to heaven!';
    elseif (stripos($name, 'obama')):
        echo "Hello, Mr. $name. Welcome to heaven!";
    else:
        echo "Hello, $name. Welcome to hell!";
    endif;

    Trong cú pháp này không sử dụng cặp dấu ngoặc {} để phân định khối code mà dùng dấu hai chấm :. Khối code kết thúc với từ khóa endif. Sau dấu hai chấm và trước từ khóa tiếp theo (elseif hoặc else) sẽ là khối code. Loại cú pháp này rất tiện lợi để chèn các đoạn văn bản HTML vào thân của lệnh.

    Tương tự như vậy chúng ta có cú pháp khác của lệnh switch-case như sau:

    <?php
    $name = readline('Your name: ');
    switch (strtolower($name)):
        case 'trump':
            $greeting = 'Mr. president!';
            break;
        case 'obama':
            $greeting = 'Mr. Obama. Great to see you!';
            break;
        case 'bush':
            $greeting = 'Mr. Bush - man of wars';
            break;
        case 'clinton':
            $greeting = 'Mr. Clinton, how is Monica!';
            break;
        default:
            $greeting = 'Welcome to PHP';
            break;
    endswitch;
    echo $greeting;

    Trong cú pháp này chúng ta thay cặp {} trong thân switch bằng dấu hai chấm và từ khóa endswitch.

    Cả cụm switch .. endswitch là một lệnh nên phải đặt dấu chấm phẩy kết thúc sau endswitch.

    Khi đến phần lập trình ứng dụng web bạn sẽ sử dụng cấu trúc mới này nhiều hơn.

    Kết luận

    + Nếu bạn thấy site hữu ích, trước khi rời đi hãy giúp đỡ site bằng một hành động nhỏ để site có thể phát triển và phục vụ bạn tốt hơn.
    + Nếu bạn thấy bài viết hữu ích, hãy giúp chia sẻ tới mọi người.
    + Nếu có thắc mắc hoặc cần trao đổi thêm, mời bạn viết trong phần thảo luận cuối trang.
    Cảm ơn bạn!

    Subscribe
    Notify of
    guest
    0 Thảo luận
    Inline Feedbacks
    View all comments