Tuỳ biến các trang báo lỗi trong CodeIgniter

Ngày 10 tháng 4 năm 2013 Trương Chương Dương
Trong thực tế, chúng ta hay có những yêu cầu phát sinh dạng như:
1. Tuỳ chỉnh các lỗi runtime error phát sinh trong code khi thực thi
2. Tuỳ chỉnh trang báo lỗi page not found khi người dùng vào một trang không có thực
3. Tuỳ chỉnh báo lỗi khi mất kết nối cơ sở dữ liệu, hoặc khi server đang quá tải khiến database không truy cập được

Đối với CI, những công việc khó khăn này thực sự vô cùng dễ dàng ;)

Mức độ 1: Tuỳ chỉnh giao diện các trang báo lỗi:

Để tuỳ biến tất cả các lỗi trong CI, bạn chỉ cần quan tâm tới thư mục application/errors (đối với CI 2.1.x) và application/view/errors đối với CI 3.0
Muốn tuỳ biến giao diện cho lỗi nào, bạn chỉ cần thay đổi nội dung của file view tương ứng là sẽ "cầu được ước thấy" một cách dễ dàng.

Cụ thể trong thư mục này sẽ có các file:

error_404.php

File này được hiển thị trong trường hợp người dùng truy cập vào một đường liên kết không có thực trên server của bạn.
File này cũng được hiển thị nếu trong code của bạn gọi function show_404(), thường được dùng để trả về lỗi nếu người dùng cố tình truy cập vào một trang có thực nhưng dữ liệu thì không hợp lệ (ví dụ ai đó cố tình hack chẳng hạn).

Trau chút một ít cho lỗi 404 là phong cách đặc trưng của các website chuyên nghiệp, để bảo đảm rằng khách hàng truy cập website luôn cảm thấy rằng website mà họ đang ghé thăm được thực hiện bởi một đội ngũ chuyên nghiệp và tận tình.
error_db.php
File này được hiển thị trong trường hợp CI không kết nối được với cơ sở dữ liệu. Một điều lưu ý là nếu bạn thực hiện một câu truy vấn mà câu đó trả về lỗi thì CI cũng load file này lên để báo lỗi.
Thông thường đối với hầu hết các hệ thống server thì trong trường hợp server quá tải ở mức độ vừa phải thì chỉ có MySQL chết còn webservices vẫn chạy nên trong trường hợp này CI sẽ hiển thị lỗi DB, cho nên đây cũng là phương án tạm ổn để thay cho thông báo lỗi hệ thống máy chủ thông thường.
error_php.php
Bất kỳ lỗi phát sinh nào trong quá trình thực thi do php trả về thì CI sẽ bắt lại và dùng file này để hiển thị. Do vậy nếu bạn nào thích tuỳ chỉnh các báo lỗi nhàm chán của PHP (ví dụ truy xuất vào biến không có thực, index của một array không tồn tại, ...) thì đây là file rất hữu ích. Tuy nhiên trong quá trình làm việc thực tế thì file này khá vô nghĩa do trên hệ thống chính thức ta nên giấu tất cả báo lỗi dạng này vì lý do bảo mật.
error_general.php
Tất cả các lỗi phát sinh mà không rơi vào bất kỳ trường hợp nào nêu trên thì sẽ rơi vào file này. Cũng gần như file error_db.php, theo kinh nghiệm thực tế mà mình thấy thì chỉ có trường hợp server quá tải nhẹ thì mới rơi vào đây.
Mức độ 2: Chặn và xử lý tất cả các lỗi theo "phong cách của bạn" không chỉ ở trên view mà phải từ trong code

Đôi khi bạn không chỉ muốn thay đổi hiển thị khi gặp lỗi mà còn muốn tự tay xử lý chúng, hoặc bạn cần phải ghi lại nhật ký tất cả các lỗi trong quá trình chạy của website. Lúc này bạn cần can thiệp vào quy trình xử lý ngoại lệ (lỗi) của CI. Nói thì phức tạp nhưng thực hiện thì cực kỳ đơn giản, bạn chỉ cần thực hiện thừa kế và mở rộng core của CI là xong. Bạn hãy thực hiện các bước sau:

Bước 1: Hãy xem file config/config.php của bạn:
Tìm dòng
PHP Code:
$config['subclass_prefix'] = 'My_'
Hãy lưu ý tới My_, điều đó có nghĩa là tất cả những file/class mở rộng của CI bắt buộc phải bắt đầu bằng tiền tố My_ và nhớ là chúng phân biệt hoa thường.
Bước 2:
PHP Code:
<?php

/**
 * Description of My_Exceptions
 *
 * @author Truong Chuong Duong
 * @email truong@chuongduong.net
 * @website http://www.chuongduong.net
 */

class My_Exceptions extends CI_Exceptions
{

    
/**
     * Controller
     *
     * @access public
     */
    
function My_Exceptions()
    {
        
parent::__construct();
    }

    
/**
     * General Error Page
     *
     * @access    private
     * @param    string    disabled - there to keep ci happy
     * @param    string    ditto for this one
     * @param    string    the error function name
     * @return    string
     */
    
function show_error($heading$message$template 'error_general'$status_code 404)
    {
        
//Ghi lại nhật ký lỗi
        
        
$log FCPATH "error_logs/" date("Y-m-d") . "-" $template ".log";

        
$date = new DateTime();
        
$date $date->format('Y-m-d H:i:s');

        
$text "";
        
$text .= "\n>>> FOUND ERROR at $date <<<";
        
$text .= "\n\t\tHeading: $heading";
        
$text .= "\n\t\tMessage: " $this->createMessage($message);
        
$text .= "\n\t\tError code: $template";
        
$text .= "\n\t\tError number: $status_code";
        
$text .= "\n\t\tServer info: " $this->createMessage($_SERVER);
        if (!empty(
$_REQUEST))
            
$text .= "\n\t\tRequest info: " $this->createMessage($_REQUEST);
        if (!empty(
$_POST))
            
$text .= "\n\t\tPost value: " $this->createMessage($_POST);
        if (!empty(
$_GET))
            
$text .= "\n\t\tGet value: " $this->createMessage($_GET);
        
$text .= "\n>>> END ERROR at $date <<<\n";

        
$f fopen($log"a");
        
fwrite($f$text);
        
fclose($f);
        
//kết thúc việc ghi nhật ký lỗi

        
if (ENVIRONMENT !== 'development')//Nếu website của bạn không phải đang hoạt động ở chế độ debug thì thay đổi báo lỗi để người dùng không biết thực sự lỗi là gì, điều này rất hữu ích cho việc bảo mật website của bạn
        
{
            
$heading "Máy chủ đang quá tải";
            
$message "Hiện tại có quá nhiều yêu cầu gửi tới cùng lúc làm máy chủ đang quá tải. Xin bạn vui lòng tải lại trang (<b>ấn nút F5</b>) sau giây lát.<br />
            Thành thật xin lỗi bạn vì sự phiền hà này, rất mong bạn thông cảm."
;
        }
        return 
parent::show_error($heading$message$template$status_code);//Trả về nội dung để hiển thị cho lỗi tương ứng
    
}

}


Vậy là xong, từ nay về sau mọi lỗi phát sinh đều được ghi lại trong thư mục error_logs, mỗi ngày được lưu trên một file khác nhau. Đừng quên tạo thư mục error_logs trong thư mục gốc của project.
Đang tải dữ liệu...