Chủ Nhật, 6 tháng 5, 2012

Căn bản lập trình web voi PHP - Bài 4(X) : PHP Căn Bản

X. "Headers Already Sent " : Thực trạng và giải pháp

Lỗi "Headers Already Sent " là 1 lỗi thông dụng đến khó tin, và tui đã nhận được rất rất nhiều câu hỏi về nó dạng như " Nó là cái gì ?, Sao lại như thế" , vì vậy tui quyết định đưa nó lên bàn mổ nhằm làm sáng tỏ vấn đề

Một HTTP response ( trả về ) thông thường bao gồm 2 phần là header( đầu) và content (nội dung), Phần header trong 1 HTTP response chỉ ra bản chất của response và  cách xử lý với chúng. Ví dụ, 1 response có chỉ ra "Location" trong header , cái này báo cho trình duyệt để tự động chuyển đến Url được chỉ ra trong header.Hoặc 1 response có "Content-type" trong header, trình duyệt sẽ xử lý nội dung theo loại nội dung :image xử khác , text xử khác, Flash xửa khác
Header cũng được sử dụng khi bạn làm việc với session, có thể bạn ko thấy rõ được điều này, nhưng trong những hàm về session của PHP nó đều dùng thông qua cookie. Vì thế ngay khi bạn dùng session bạn đã tạo ra 1 HTTP header. Hàm session_start() khởi tạo 1 tập cookie và vì thế nó gửi 1 HTTP header xuống trình duyệt.
Phần còn lại của HTTP response là nội dung (content), cái này chắc bạn nhìn thấy nó dễ dàng rồi. Phần này phải được gửi đi sau headers, và một khi nội dung đã được gửi đi thì sẽ ko có header nào có thể được gửi xuống trình duyệt nữa. Nội dung bao gồm các đoạn mã HTML hoặc bất cứ thứ gì được tạo ra trong script của bạn. Khi bạn gọi echo() bạn đã xuất nội dung xuống trình duyệt rồi đấy.

Thế thì liên quan gì đến lỗi "Headers Already Sent"? Lỗi này xuất hiện khi bạn cố gắng gửi 1 HTTP header xuống trình duyệt sau khi nội dung đã được gửi xuống. Trong một HTTP response đều này là phạm pháp , ko được phép bởi vì " gạo đã nấu thành cơm"  , trình duyệt đã xử lý xong phần nội dung được gửi xuống rồi, header ko còn tác dụng gì nữa cả .

Và như tớ đã nói ở trên, session_start() gửi header xuống client, hàm header() cũng gửi header xuống ... vì thế 2 thằng này là dễ gặp lỗi "Headers Already Sent" nhất nếu như đã gửi nội dung xuống trình duyệt trước khi gọi chúng.

Giải pháp cho vấn đề này đơn giản chỉ là : hãy chắc chắn rằng bạn không gửi bất cứ nội dung gì xuống trình duyệt trước khi gọi các hàm có làm việc với header.Nói thì như thế nhưng thực tế cũng khá khó khăn vì ... chúng ta là người Việt, chúng ta phải viết tiếng Việt trong code , chúng ta phải dùng Unicode ... và đa số các Editor PHP , khi bạn chọn encoding cho file là Utf-8 nó sẽ vô tư kèm theo cho bạn 3 kí tự ở đầu file gọi là BOM (byte order mark) ( dịch ra là gì thì tớ ko biết ), các kí tự này thuộc dạng vô hình nên chúng ta sẽ ko nhìn thấy chúng , nhưng máy tính thì thấy.... vì thế cho nên bạn có bỏ ra cả tháng trời để ngồi mò mẫm trong code xem có kí tự nào được xuất ra hay chưa thì cũng vô vọng . Cách đơn giản nhất là hãy chọn Utf-8 witthout BOM trong Editor của bạn .

Nhưng có một giải pháp khác an toàn nhàn nhã hơn là hãy giao tất cả những gì bạn xuất ra cho bộ đệm (output buffering ) nắm giữ, sau khi xử lý xong tất cả sẽ được cho vào đại pháo bắn 1 lần xuống trình duyệt ... không cần lo sau trước thứ tự gì nữa cả . Hãy thêm vào đầu code của bạn ob_start() và cuối code ob_end_flush(), bạn có thể vừa code vừa ngủ , để biết thêm về những hàm output buffering  hãy tìm đến PHP Manual .
 

Không có nhận xét nào:

Đăng nhận xét

Học lập trình web căn bản với PHP

Bài 1: Các kiến thức căn bản Part 1:  https://jimmyvan88.blogspot.com/2012/05/can-ban-lap-trinh-web-voi-php-bai-1-cac.html Part 2:  https://...