PHP: header()
Phiên bản áp dụng: PHP 4, PHP 5, PHP 7.
Cú pháp
void header ( string $string
[, bool $replace
= true [, int $http_response_code
]] )
Mục đích: header() dùng để gửi một header HTTP ở dạng thô.
Cần nhớ rằng header() phải được gọi trước khi gửi bất kỳ điều gì tới output như các thẻ HTML, dòng trắng trong một file, hoặc từ PHP. Đây là một lỗi rất phổ biến khi đọc code với include hay require, các hàm hoặc hàm truy cập file, và có những khoảng trống hay các dòng trắng ở đầu ra trước khi header() được gọi. Vấn đề tương tự cũng được bắt gặp khi sử dụng tập tin PHP/HTML.
Ví dụ:
<html>
<?php
/* Ở đây sẽ phát sinh lỗi vì xuất hiện thẻ <html>
* trước lời gọi header() */
header('Location: http://www.example.com/');
exit;
?>
Các tham số
string
Chuỗi header.
Có hai lời gọi header đặc biệt. Trường hợp thứ nhất là chuỗi chứa "HTTP/" (không nhiều), trường hợp này sẽ được dùng để cấu hình ngoài mã trạng thái HTTP để gửi. Ví dụ như nếu bạn cấu hình Apache để sử dụng kịch bản PHP để xử lý các yêu cầu đối với việc thiếu các tập tin (dùng chỉ thị ErrorDocument) thì bạn có thể muốn đảm bảo rằng kịch bản của bạn tạo ra mã trạng thái thích hợp. Ví dụ:
<?php
header("HTTP/1.0 404 Not Found");
?>
Trường hợp đặc biệt thứ hai là chuỗi có chứa "Location:". Chỉ thị này không những gửi header trở lại trình duyệt mà còn trả về cho trình duyệt mã trạng thái REDIRECT (302) trừ khi mã trạng thái 201 hoặc 3xx đã được thiết lập từ trước. Ví dụ:
<?php
header("Location: http://www.example.com/"); /* Gửi trực tiếp tới trình duyệt */
/* Cần đảm bảo rằng đoạn mã bên dưới không được thực thi khi ta điều hướng. */
exit;
?>
replace
Tham số tùy chọn này chỉ ra header nên thay thế header tương tự trước đó, hoặc thêm header thứ hai cùng loại. Mặt định thì nó sẽ thay thế, nhưng nếu truyền giá tri FALSE
vào đối số này thì ta có thể thiết lập nhiều header khác cùng loại. Ví dụ:
<?php
header('WWW-Authenticate: Negotiate');
header('WWW-Authenticate: NTLM', false);
?>
http_response_code
Tham số này tạo mã phản hồi HTTP với giá trị xác định. Lưu ý rằng tham số này chỉ có tác dụng nếu tham số string
không trống.
Giá trị trả về
header() không có giá trị trả về.
Changelog
Phiên bản | Mô tả |
---|---|
5.1.2 | Phiên bản hiện tại có thể ngăn cản không có phép cùng lúc gửi nhiều header nhằm mục đích bảo vệ chống lại những cuộc tấn công injection đối với header. |
Ví dụ
Ví dụ 1: Tải xuống hộp thoại
Nếu bạn muốn nhắc người dùng rằng cần lưu dữ liệu bạn đang gửi, ví dụ như tập tin PDF chẳng hạn, thì bạn sử dụng header Content-Disposition để cung cấp tên file khuyến nghị và yêu cầu trình duyệt hiển thị hộp thoại lưu trữ.
<?php
// Output một file PDF
header('Content-Type: application/pdf');
// Gọi file downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');
// PDF nguồn là original.pdf
readfile('original.pdf');
?>
Ví dụ 2: Các chỉ thị bộ nhớ đệm
Các kịch bản PHP thường tạo nội dung động nhưng không được đệm ở trình duyệt client hoặc bất kỳ bộ nhớ đệm proxy nào giữa trình duyệt client và server. Nhiều proxy and client có thể bị ép buộc cấm sử dụng bộ nhớ đệm bằng cách thức như sau:
<?php
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Ngày hết hạn
?>
Lưu ý là bạn có thể nhận thấy rằng các trang của bạn không được đệm mặc dù bạn không hề sử dụng các header trên. Có một số tùy chọn mà người dùng có thể cho phép thiết lập đối với trình duyệt để có thể mặc định thực hiện việc đệm trang. Bằng cách gửi các header ở trên thì ta cần ghi đè các cài đặt nhằm mục đích trang của ta được đệm trên bộ nhớ cache của trình duyệt.
Ngoài ra thì việc sử dụng hàm session_cache_limiter() và việc thiết lập cấu hình session.cache_limiter có thể được sử dụng để tự động tạo các header đệm chuẩn khi ta sử dụng các session.
Các lưu ý khi sử dụng header()
- Các header sẽ chỉ có thể được truy cập và sử dụng khi một SAPI hỗ trợ chúng đang được sử dụng.
- Ta có thể sử dụng bộ đệm đầu ra để thực hiện vấn đề này bằng chi phí của tất cả các đầu ra của bạn tới trình duyệt được đệm trong server cho tới khi bạn gửi nó. Ta có thể thực hiện điều này bằng cách gọi các hàm ob_start() và ob_end_flush() trong kịch bản, hoặc thiết lập chỉ thị cấu hình output_buffering trong tập tin php.ini hoặc các tập tin cấu hình server.
- Dòng header trạng thái HTTP sẽ luôn luôn được gửi tới client đầu tiên bất kể là ta có gọi hàm actualheader() đầu tiên hay không. Trạng thái có thể được ghi đè bằng cách gọi header() với một dòng trạng thái mới bất kỳ lúc nào trừ khi các header HTTP đã được gửi rồi.
- Nếu chế độ safe mode được kích hoạt thì uid của kịch bản sẽ được thêm vào phần realm của header WWW-Authenticate nếu bạn thiết lập header này (sử dụng cho HTTP Authentication).
- Hầu hết khách hàng hiện nay đều chập nhận các URI tương đối là đối số của Location, nhưng có một số khách có thể yêu cầu URI tuyệt đối bao gồm scheme, hostname và đường dẫn tuyệt đối. Do vậy, ta có thể sử dụng $_SERVER['HTTP_HOST'], $_SERVER['PHP_SELF'] và dirname() để tạo URI tuyệt đối từ như sau:
<?php
/* Chuyển hướng đến một trang khác trong thư mục hiện tại đã được yêu cầu */
$host = $_SERVER['HTTP_HOST'];
$uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
$extra = 'mypage.php';
header("Location: http://$host$uri/$extra");
exit;
?>
- Session ID không được truyền đi khi dùng header Location ngay cả khi session.use_trans_sid được kích hoạt, mà nó phải được truyền bằng cách sử dụng hằng SID.