ฉันมีสคริปต์ PHP ที่ต้องตอบกลับด้วยรหัสตอบกลับ HTTP (รหัสสถานะ) เช่น HTTP 200 OK หรือรหัส 4XX หรือ 5XX
ฉันจะทำสิ่งนี้ใน PHP ได้อย่างไร
ฉันมีสคริปต์ PHP ที่ต้องตอบกลับด้วยรหัสตอบกลับ HTTP (รหัสสถานะ) เช่น HTTP 200 OK หรือรหัส 4XX หรือ 5XX
ฉันจะทำสิ่งนี้ใน PHP ได้อย่างไร
คำตอบ:
ฉันเพิ่งพบคำถามนี้และคิดว่ามันต้องการคำตอบที่ครอบคลุมมากขึ้น:
ในฐานะของPHP 5.4มีสามวิธีในการทำสิ่งนี้:
header()
ฟังก์ชั่นพิเศษที่มีการใช้งานในกรณีที่ตรวจพบสายตอบสนอง HTTP และช่วยให้คุณสามารถแทนที่ด้วยหนึ่งที่กำหนดเอง
header("HTTP/1.1 200 OK");
อย่างไรก็ตามต้องมีการดูแลเป็นพิเศษสำหรับ CGI PHP (เร็ว):
$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) == 'cgi')
header("Status: 404 Not Found");
else
header("HTTP/1.1 404 Not Found");
หมายเหตุ:ตามที่RFC HTTPที่วลีเหตุผลสามารถเป็นสตริงที่กำหนดเองใด ๆ (ที่สอดคล้องกับมาตรฐาน) แต่เพื่อประโยชน์ของการทำงานร่วมกันของลูกค้าที่ผมไม่แนะนำให้ใส่สตริงแบบสุ่มมี
หมายเหตุ: php_sapi_name()
ต้องใช้PHP 4.0.1
เห็นได้ชัดว่ามีปัญหาเล็กน้อยเมื่อใช้ตัวแปรชุดแรก ที่ใหญ่ที่สุดที่ฉันคิดว่ามันเป็นส่วนแยกโดย PHP หรือเว็บเซิร์ฟเวอร์และเอกสารไม่ดี
ตั้งแต่ 4.3 header
ฟังก์ชันมีอาร์กิวเมนต์ที่ 3 ที่ให้คุณตั้งรหัสตอบกลับได้อย่างสะดวกสบาย แต่การใช้มันต้องการอาร์กิวเมนต์แรกเป็นสตริงที่ไม่ว่างเปล่า นี่คือสองตัวเลือก:
header(':', true, 404);
header('X-PHP-Response-Code: 404', true, 404);
ฉันแนะนำอันที่สอง ครั้งแรกไม่ทำงานในเบราว์เซอร์ทั้งหมดที่ผมได้ทดสอบ แต่บางเล็กน้อยเบราว์เซอร์หรือโปรแกรมรวบรวมข้อมูลเว็บอาจมีปัญหากับสายส่วนหัวที่มีเพียงลำไส้ใหญ่ได้ ชื่อฟิลด์ส่วนหัวในลำดับที่ 2 ตัวแปรเป็นของหลักสูตรที่ไม่ได้มาตรฐานในทางใดทางหนึ่งและสามารถแก้ไขได้ฉันเพียงแค่เลือกชื่อที่สื่อความหมายด้วยความหวัง
http_response_code()
ฟังก์ชั่นได้รับการแนะนำใน PHP 5.4 และจะทำสิ่งที่เป็นจำนวนมากได้ง่ายขึ้น
http_response_code(404);
นั่นคือทั้งหมดที่
นี่คือฟังก์ชั่นที่ผมได้ปรุงขึ้นเมื่อผมจำเป็นต้องมีการทำงานร่วมกันดังต่อไปนี้ 5.4 แต่อยากทำงานของ "ใหม่ที่" http_response_code
ฟังก์ชั่น ฉันเชื่อว่า PHP 4.3 นั้นรองรับความเข้ากันได้มากกว่าที่เคยมีมา แต่คุณไม่รู้ ...
// For 4.3.0 <= PHP <= 5.4.0
if (!function_exists('http_response_code'))
{
function http_response_code($newcode = NULL)
{
static $code = 200;
if($newcode !== NULL)
{
header('X-PHP-Response-Code: '.$newcode, true, $newcode);
if(!headers_sent())
$code = $newcode;
}
return $code;
}
}
headers_sent()
เป็นจริงทันทีหลังจากโทรheader()
หรือไม่ (2) เคยพบอะไรเช่น http_response_text () ใน 5.4 โลกหรือไม่ อย่างน้อยส่วนหัวเก่า () สามารถส่งผลต่อข้อความหลังจากรหัสสถานะ
headers_sent()
เป็นจริงถ้าคุณไม่สามารถเพิ่มส่วนหัวใด ๆ อีกต่อไปเพราะเนื้อหาถูกส่งไปแล้วไม่ใช่ถ้าคุณได้เพิ่มส่วนหัว (2)ขออภัยค่ะ ภาษาอื่นมีการสนับสนุนที่ดีกว่า
http_response_code
(และโดยทั่วไปอาจแก้ไขส่วนหัว) ไม่ทำงานอีกต่อไปหลังจากที่คุณทำecho
อะไรบางอย่าง หวังว่ามันจะช่วย
น่าเสียดายที่ฉันพบโซลูชันที่นำเสนอโดย @ualual มีข้อบกพร่องต่าง ๆ
การใช้substr($sapi_type, 0, 3) == 'cgi'
ไม่ใช่ enogh เพื่อตรวจจับ CGI ที่รวดเร็ว เมื่อใช้ PHP-FPM FastCGI Process Manager php_sapi_name()
จะส่งคืน fpm ไม่ใช่ cgi
Fasctcgi และ php-fpm เปิดเผยข้อผิดพลาดอื่นที่กล่าวถึงโดย @Josh - การใช้header('X-PHP-Response-Code: 404', true, 404);
ทำงานได้อย่างถูกต้องภายใต้ PHP-FPM (FastCGI)
header("HTTP/1.1 404 Not Found");
อาจล้มเหลวเมื่อโปรโตคอลไม่ใช่ HTTP / 1.1 (เช่น 'HTTP / 1.0') ต้องตรวจพบโปรโตคอลปัจจุบันโดยใช้$_SERVER['SERVER_PROTOCOL']
(มีให้ตั้งแต่ PHP 4.1.0
อย่างน้อย 2 กรณีเมื่อเรียกhttp_response_code()
ผลลัพธ์ทำให้เกิดพฤติกรรมที่ไม่คาดคิด:
มีรายการรหัสสถานะการตอบสนอง HTTP เต็มรูปแบบ (รายการนี้รวมถึงรหัสจากมาตรฐานอินเทอร์เน็ต IETF รวมถึง IETF RFCs อื่น ๆ ส่วนใหญ่ไม่ได้รับการสนับสนุนโดยฟังก์ชัน PHP http_response_code PHP): http: //th.wikipedia .org / วิกิพีเดีย / List_of_HTTP_status_codes
คุณสามารถทดสอบข้อผิดพลาดนี้ได้อย่างง่ายดายโดยโทร:
http_response_code(521);
เซิร์ฟเวอร์จะส่งรหัสตอบกลับ HTTP "ข้อผิดพลาดเซิร์ฟเวอร์ภายใน 500" ทำให้เกิดข้อผิดพลาดที่ไม่คาดคิดหากคุณมีตัวอย่างเช่นแอปพลิเคชันไคลเอนต์แบบกำหนดเองที่โทรหาเซิร์ฟเวอร์ของคุณและคาดหวังรหัส HTTP เพิ่มเติม
โซลูชันของฉัน (สำหรับ PHP ทุกรุ่นตั้งแต่ 4.1.0):
$httpStatusCode = 521;
$httpStatusMsg = 'Web server is down';
$phpSapiName = substr(php_sapi_name(), 0, 3);
if ($phpSapiName == 'cgi' || $phpSapiName == 'fpm') {
header('Status: '.$httpStatusCode.' '.$httpStatusMsg);
} else {
$protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
header($protocol.' '.$httpStatusCode.' '.$httpStatusMsg);
}
ข้อสรุป
การใช้งาน http_response_code () ไม่สนับสนุนรหัสตอบกลับ HTTP ทั้งหมดและอาจเขียนทับรหัสตอบกลับ HTTP ที่ระบุกับอีกกลุ่มหนึ่งจากกลุ่มเดียวกัน
ฟังก์ชัน http_response_code () ใหม่ไม่สามารถแก้ปัญหาทั้งหมดที่เกี่ยวข้อง แต่ทำสิ่งที่เลวร้ายที่สุดในการแนะนำข้อบกพร่องใหม่
โซลูชัน "ความเข้ากันได้" ที่นำเสนอโดย @dualed ไม่ทำงานอย่างที่คาดไว้อย่างน้อยภายใต้ PHP-FPM
โซลูชันอื่น ๆ ที่นำเสนอโดย @ualualed ยังมีข้อบกพร่องต่าง ๆ การตรวจจับ CGI ที่รวดเร็วไม่รองรับ PHP-FPM ต้องตรวจพบโปรโตคอลปัจจุบัน
การทดสอบและความคิดเห็นใด ๆ ที่ชื่นชม
ตั้งแต่ PHP 5.4 คุณสามารถใช้http_response_code()
เพื่อรับและตั้งค่ารหัสสถานะส่วนหัว
นี่คือตัวอย่าง:
<?php
// Get the current response code and set a new one
var_dump(http_response_code(404));
// Get the new response code
var_dump(http_response_code());
?>
นี่คือเอกสารของฟังก์ชั่นนี้ใน php.net:
เพิ่มบรรทัดนี้ก่อนการส่งออกใด ๆ ของร่างกายในกรณีที่คุณไม่ได้ใช้บัฟเฟอร์การส่งออก
header("HTTP/1.1 200 OK");
แทนที่ส่วนข้อความ ('ตกลง') ด้วยข้อความที่เหมาะสมและรหัสสถานะด้วยรหัสของคุณตามความเหมาะสม (404, 501, ฯลฯ )
หากคุณอยู่ที่นี่เพราะ Wordpress ให้ 404 เมื่อโหลดสภาพแวดล้อมสิ่งนี้ควรแก้ไขปัญหา:
define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
status_header( 200 );
//$wp_query->is_404=false; // if necessary
ปัญหาเกิดจากการส่งสถานะ: 404 หัวข้อไม่พบ คุณต้องลบล้างสิ่งนั้น สิ่งนี้จะได้ผล:
define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
header("HTTP/1.1 200 OK");
header("Status: 200 All rosy");
ด้วยฟังก์ชั่นส่วนหัว มีตัวอย่างในส่วนของพารามิเตอร์แรกที่ใช้
header("HTTP/1.1 200 OK");
http_response_code(201);
header("Status: 200 All rosy");
http_response_code (200); ไม่ทำงานเพราะทดสอบการแจ้งเตือน 404 https://developers.google.com/speed/pagespeed/insights/
หากรุ่น PHP ของคุณไม่มีฟังก์ชั่นนี้:
<?php
function http_response_code($code = NULL) {
if ($code !== NULL) {
switch ($code) {
case 100: $text = 'Continue';
break;
case 101: $text = 'Switching Protocols';
break;
case 200: $text = 'OK';
break;
case 201: $text = 'Created';
break;
case 202: $text = 'Accepted';
break;
case 203: $text = 'Non-Authoritative Information';
break;
case 204: $text = 'No Content';
break;
case 205: $text = 'Reset Content';
break;
case 206: $text = 'Partial Content';
break;
case 300: $text = 'Multiple Choices';
break;
case 301: $text = 'Moved Permanently';
break;
case 302: $text = 'Moved Temporarily';
break;
case 303: $text = 'See Other';
break;
case 304: $text = 'Not Modified';
break;
case 305: $text = 'Use Proxy';
break;
case 400: $text = 'Bad Request';
break;
case 401: $text = 'Unauthorized';
break;
case 402: $text = 'Payment Required';
break;
case 403: $text = 'Forbidden';
break;
case 404: $text = 'Not Found';
break;
case 405: $text = 'Method Not Allowed';
break;
case 406: $text = 'Not Acceptable';
break;
case 407: $text = 'Proxy Authentication Required';
break;
case 408: $text = 'Request Time-out';
break;
case 409: $text = 'Conflict';
break;
case 410: $text = 'Gone';
break;
case 411: $text = 'Length Required';
break;
case 412: $text = 'Precondition Failed';
break;
case 413: $text = 'Request Entity Too Large';
break;
case 414: $text = 'Request-URI Too Large';
break;
case 415: $text = 'Unsupported Media Type';
break;
case 500: $text = 'Internal Server Error';
break;
case 501: $text = 'Not Implemented';
break;
case 502: $text = 'Bad Gateway';
break;
case 503: $text = 'Service Unavailable';
break;
case 504: $text = 'Gateway Time-out';
break;
case 505: $text = 'HTTP Version not supported';
break;
default:
exit('Unknown http status code "' . htmlentities($code) . '"');
break;
}
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header($protocol . ' ' . $code . ' ' . $text);
$GLOBALS['http_response_code'] = $code;
} else {
$code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
}
return $code;
}
เราสามารถรับผลตอบแทนที่แตกต่างจาก http_response_code ผ่านสภาพแวดล้อมที่แตกต่างกันสองแบบ:
ที่เว็บเซิร์ฟเวอร์ให้ส่งคืนรหัสตอบกลับก่อนหน้าหากคุณระบุรหัสตอบกลับหรือเมื่อคุณไม่ได้ระบุรหัสตอบกลับใด ๆ จากนั้นจะพิมพ์ค่าปัจจุบัน ค่าเริ่มต้นคือ 200 (OK)
ที่ CLI Environment ความจริงจะถูกส่งคืนหากคุณระบุรหัสตอบกลับและเป็นเท็จหากคุณไม่ได้ให้รหัสการตอบกลับใด ๆ
ตัวอย่างของเว็บเซิร์ฟเวอร์สภาพแวดล้อมของค่าส่งคืนของ Response_code:
var_dump(http_respone_code(500)); // int(200)
var_dump(http_response_code()); // int(500)
ตัวอย่างของ CLI Environment ของ Response_code ค่าส่งคืน:
var_dump(http_response_code()); // bool(false)
var_dump(http_response_code(501)); // bool(true)
var_dump(http_response_code()); // int(501)
header('X-PHP-Response-Code: 404', true, 404);
ทำงานได้อย่างถูกต้องภายใต้PHP-FPM (FastCGI)