Liên hệ
lập trình php

Error và Exception trong lập trình PHP

Bắt lỗi và sử lỗi trong PHP, sử dụng các câu lệnh try catch và tạo hàm mặc định xử lý lỗi với exception_handler và error_handler

Phần này trình bày các vấn đề liên quan đến Error và Exception trong PHP. PHP có cung cấp các cơ chế giúp bắt lỗi, giám sát các lỗi và xử lý các lỗi có thể xảy ra khi lập trình.

Hàm die() và exit()

Hàm dieexit là tương đương nhau. Gọi hàm này để dừng chương trình ngay lập tức. Cú pháp gọi hàm này như sau:

exit ([$status])
//hoặc
exit ( int $status )

$status là dòng trạng thái in ra trước khi thoát. Hoặc là một số nguyên được hiểu là trang thái khi thoát (0 - 255). 0 cho biết chương trình thoát ra một cách bình thường (không lỗi).

Ví dụ, nếu không mở được file thì kết thúc chương trình:

<?php

    $filename = '/path/to/data-file';
    $file = fopen($filename, 'r')
        or exit("unable to open file ($filename)");

?>

Ngoại lệ Exception trong PHP

throw và lớp Exception

Khi lập trình, bạn cần phát sinh các ngoại lệ thì bạn cần tạo một đối tượng ngoại lệ từ lớp Exception hoặc một lớp nào đó mà kế thừa từ Exception như (ErrorException, ), trong PHP7 còn có thêm Error, Throwable, TypeError ... Sau đó để phát sinh ngoại lệ để chương trình chuyển hướng theo ngoại lệ bạn cần cú pháp throw $exception;, các lệnh tiếp sau throw trong một block sẽ không được thi hành.

Ví dụ hàm sau phát sinh một ngoại lệ Exception, nếu số đó là 0 và một ngoại lệ khác là ErrorException nếu số đó nhỏ hơn 0.

<?
    function cal($number) {
        if ($number <0 ) {
            $exception = new Exception('Lỗi do số nhỏ hơn 0');
            throw $exception;
        }
        else if ($number == 0 ) {
            $exception = new ErrorException('Lỗi do số bằng 0');
            throw $exception;
        }

        return ++$number;

    }

    cal(-1);
    //Chạy hàm trên PHP hiện thị thông báo lỗi ...
?>

Khi có đoạn code gọi lệnh throw như trên, chương trình sẽ điều hướng tới hàm bắt lỗi mặc định của PHP hàm này sẽ hiện thị các thông tin lỗi và kết thúc chương trình. Phần sau sẽ thảo luận cách xây dựng hàm này và đăng ký với PHP

Sử dụng try ... catch ... để bắt ngoại lệ

Giờ thay vì để hàm xử lỗi của PHP xử lý các Exception như trên, bạn muốn bắt các lỗi này ngay trong đoạn code xảy ra lỗi, để xử lý kết thúc hoặc chạy tiếp theo yêu cầu của bạn, lúc này bạn dùng cú pháp lệnh try ... catch .... Cú pháp cơ bản như sau:

try 
{
    //Khối lệnh mà có thể phát sinh Exception
} 
catch (Exception $e) 
{    
    //Khối lệnh bắt được Exception
}

Nếu sử dụng code try ... catch ... như trên, thì code trong khối try nếu phát sinh exception thì chương trình không kết thúc mà chuyển hướng tới khối catch với thông tin về Exception là bến $e

Trở lại ví dụ trên, viết để bắt ngoại lệ như sau:

<?php
function cal($number) {
    if ($number <0 ) {
        $exception = new Exception('Lỗi số nhỏ hơn 0');
        throw $exception;
    }
    else if ($number == 0 ) {
        $exception = new ErrorException('Lỗi số bằng 0');
        throw $exception;
    }

    return ++$number;

}

try {
    cal(-1);
}
catch (Exception $e) {
    echo $e->getMessage();
} 

Bạn có thể sử dụng nhiều khối try để bắt các loại Exception khác nhau, ví dụ:

<?php
function cal($number) {
    if ($number <0 ) {
        $exception = new Exception('Lỗi số nhỏ hơn 0');
        throw $exception;
    }
    else if ($number == 0 ) {
        $exception = new ErrorException('Lỗi số bằng 0');
        throw $exception;
    }

    return ++$number;

}

try {
    cal(0);
}
catch (Exception $e) {      //khối 1
    echo 'Lỗi Exception:';
    echo $e->getMessage();
} 
catch (ErrorException $e) { //khối 2
    echo 'Lỗi ErrorException:';
    echo $e->getMessage();
} 

Trong cú pháp try ... catch ... bạn cũng có thể tạo ra một khối ở cuối cùng có tên là finally, các code trong khối này luôn được thi hành

<?php
try {
    //...
} catch (Exception $e) {
    //...
} finally {
    //...Code luôn thi hành
}

Tạo các Exception riêng

Nếu lớp Exception mặc định như Exception, ErrorException chưa đủ dùng cho bạn, bạn có thể tạo ra các Exeption riêng bằng cách kế thừa lớp Exception

<?
class MyExption extends Exception {
    //Định nghĩa các hàm riêng của bạn, ví dụ:
    public function errorMessage() {
        $errorMsg = 'Lỗi tại dòng '.
        $this->getLine().' trong file '.$this->getFile();
        return $errorMsg;
    }
}
?>

//Lúc này MyExption có thể được tạo bằng
//$e = new MyExption("Thông báo lỗi");

Tạo exception_handlererror_handler riêng

set_exception_handler

Khi ứng dụng phát sinh ngoại lệ bằng lệnh throw, nếu ngoại lệ không bị bắt lại bằng khối lệnh try ... catch ... thì ngoại lệ đó sẽ chuyển cho hàm xử lý ngoại lệ mặc định của PHP. Giờ nếu bạn muốn tạo ra hàm mặc định này thì làm như sau: Tạo hàm riêng xử lý ngoại lệ có dạng function my_exception_handler($exception), sau đó dùng hàm set_exception_handler('my_exception_handler') để đăng ký với PHP. Ví dụ:

<?php 
function exception_handler($exception) { 
  echo "Bắt được lỗi: " , $exception->getMessage(), "\n"; 
} 
 
set_exception_handler('exception_handler'); 
 
throw new Exception('Một ngoại lệ phát sinh'); 
 
echo "Sau lệnh throw nên không thi hành được\n"; 
?> 

set_error_handler

Ngoài các ngoại lệ phát sinh do logic chương trình ra, ứng dụng có thể xảy ra các lỗi nghiêm trọng khác nhau trong quá trình chạy. Để định nghĩa hàm riêng các lỗi này thì bạn làm như sau: Tạo hàm riêng xử lý lỗi có dạng function myErrorHandler($errno, $errstr, $errfile, $errline), sau đó dùng hàm set_error_handler('myErrorHandler') để đăng ký với PHP. Ví dụ:

<?php
error_reporting( E_ERROR );
function handleError($errno, $errstr,$error_file,$error_line)
{
    echo "<b>Lỗi:</b> [$errno] $errstr - $error_file: $error_line";
    echo "<br />";
    echo "Kết thúc!";
    die();
}

set_error_handler("handleError");

Bạn có thể một framework chuyên về error handler và exception handler whoops

Vui lòng đăng ký ủng hộ kênh