Hãy cố gắng throw Exception khi gặp lỗi

Trong quá trình làm việc, với PHP nói riêng và các ngôn ngữ lập trình nói chung, bạn sẽ dễ dàng gặp các trường hợp mà giá trị bị sai. Vậy lúc đó bạn giải quyết nó như thế nào? Return False? Return một đoạn message để biết đó là lỗi gì? Hãy cố gắng throw Exception nếu có thể.

Return FALSE

Việc throw Exception giúp bạn có được một cơ chế quản lý lỗi rõ ràng và hợp lý. Tại sao lại như vậy? Hãy xét ví dụ:
function getPost($id)
{
    // Check post exist
    $post = postLoad($id);
    if ($post == null) {
        return false;
    }

    // Check status publish
    if ($post->getStatus == 'review') {
        return false;
    }
    //...
}
Phía trên là function getPost đơn giản. Để get post, bạn phải thực hiện các thao tác: check id là int > 0, check nó có tồn tại, check nó có status đã publish, check nó không bị khóa đối với user, bla bla…
Khi sử dụng function đơn giản phía trên, nếu giá trị nó trả về là false, làm sao bạn biết đó là lỗi logic của đoạn check nào? Và việc return false một cách cứng nhắc như vậy làm cho function này khó có thể mở rộng.

Exception

PHP cung cấp cho bạn một class chuyên xử lý lỗi là Exception class. Việc của bạn chỉ là ném lỗi cho nó thôi. Ngoài ra bạn cũng có thể tự define Exception class của riêng mình để sử dụng cho các mục đích chuyên biệt hơn.
Để define 1 Exception mới, bạn chỉ cần extends Exception class mặc định của PHP là được. Lợi ích của class Exception tự define đó là bạn có thể thêm nhiều thuộc tính hơn để log lỗi.
Ví dụ
class PostStatusException extends Exception
{
    protected $post;

    public function __construct($message, $post = null)
    {
        parent::__construct($message);

        $this->post = $post;
    }

    public function getPost()
    {
        return $this->post;
    }
}

Với class PostStatusException vừa define, bạn có thể lấy được $post object khi lỗi này xảy ra.

Throw Exception

Vậy, function getPost phía trên, bạn nên throw ra Exception thay vì return False. Khi throw ra Exception, bạn có thể kèm theo message hoặc không, tốt nhất là cứ điền thêm message cho rõ ràng, rành mạch, chả mất gì.
function getPost($id)
{
    // Check post exist
    $post = postLoad($id);
    if ($post == null) {
        throw new NotFoundException('Post not exist');
    }

    // Check status publish
    if ($post->getStatus == 'review') {
        throw new PostStatusException('Post is review', $post);
    }
    //...
}
Âu cơ, Exception thì đã ném ra, vậy bắt nó như thế nào?

Bắt Exception bằng try - catch

Khi sử dụng hàm getPost phía trên, nếu có lỗi, PHP sẽ tự động ném lỗi ra màn hình hiển thị.
$post = getPost($id);
Vậy để bắt nó, tùy biến nó, log nó thì sao? Sử dụng try - catch thôi
try {
    $post = getPost($id);
} catch (NotFoundException $e) {
    // Alert not found post, log error
} catch (PostStatusException $e) {
    $post = $e->getPost();
    // You can send mail to admin publish post,...
}

Tổng kết

Việc throw Exception cho ta một cơ chế quản lý lỗi rõ ràng và minh bạch. Nó giúp ta biết được lỗi mà mình đang mắc phải là gì. Điều này cực kì hữu ích trong quá trình debug lỗi. Nếu như return false, bạn sẽ phải debug từng đoạn false để xem lỗi, chắc chết :P