질문 : PHP에서 "Headers already sent"오류를 수정하는 방법
내 스크립트를 실행할 때 다음과 같은 몇 가지 오류가 발생합니다.
경고 : 헤더 정보를 수정할 수 없습니다 -23 행의 /some/file.php에서 (/some/file.php:12에서 시작된 출력) 이미 보낸 헤더
오류 메시지에 언급 된 줄에는 header()
및 setcookie()
호출이 포함됩니다.
그 이유는 무엇일까요? 그리고 그것을 고치는 방법?
답변
HTTP 헤더를 전송 / 수정하는 함수는 출력이 이루어지기 전에 호출되어야합니다.
그렇지 않으면 호출이 실패합니다.
경고 : 헤더 정보를 수정할 수 없습니다. 헤더가 이미 전송되었습니다 ( script : line 에서 시작된 출력).
HTTP 헤더를 수정하는 일부 기능은 다음과 같습니다.
출력은 다음과 같습니다.
- 의도하지 않은 :
<?php
앞 또는?>
- 특히 UTF-8 바이트 순서 표시
- 이전 오류 메시지 또는 알림
- 의도적 :
print
,echo
및 출력을 생성하는 기타 기능<?php
코드 이전의 원시<html>
헤더를 출력하기 전에 전송해야하는 이유를 이해하려면 일반적인 HTTP 응답을 살펴 봐야합니다. PHP 스크립트는 주로 HTML 콘텐츠를 생성하지만 HTTP / CGI 헤더 세트를 웹 서버에 전달하기도합니다.
HTTP/1.1 200 OK
Powered-By: PHP/5.3.7
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
<html><head><title>PHP page output page</title></head>
<body><h1>Content</h1> <p>Some more output follows...</p>
and <a href="/"> <img src=internal-icon-delayed> </a>
페이지 / 출력은 항상 헤더를 따릅니다. PHP는 먼저 헤더를 웹 서버에 전달해야합니다. 한 번만 할 수 있습니다. 이중 줄 바꿈 후에는 더 이상 수정할 수 없습니다.
PHP가 첫 번째 출력 ( print
, echo
, <html>
)을 받으면 수집 된 모든 헤더를 플러시합니다. 그 후 원하는 모든 출력을 보낼 수 있습니다. 그러나 추가 HTTP 헤더를 보내는 것은 불가능합니다.
header()
경고에는 문제 원인을 찾기위한 모든 관련 정보가 포함되어 있습니다.
경고 : 헤더 정보를 수정할 수 없습니다-100 행의 /www/usr2345/htdocs/index.php에서 이미 보낸 헤더 (/ www / usr2345 / htdocs / auth.php : 52 에서 시작된 출력 )
여기서 "line 100"은 header()
호출이 실패한 스크립트를 나타냅니다.
괄호 안의 "에서 시작된 "출력이 더 중요합니다. 이전 출력의 소스를 나타냅니다. 이 예에서는 auth.php
및 줄 52
입니다. 그것이 조기 출력을 찾아야하는 곳입니다.
일반적인 원인 :
- print, echo
print
및echo
문의 의도적 인 출력은 HTTP 헤더를 보낼 기회를 종료합니다. 이를 방지하기 위해 애플리케이션 흐름을 재구성해야합니다. 함수 와 템플릿 체계를 사용합니다. 메시지를 작성 하기 전에header()
호출이 발생하는지 확인하십시오. 출력을 생성하는 함수는 다음과 같습니다.print
,echo
,printf
,vprintf
trigger_error
,ob_flush
,ob_end_flush
,var_dump
,print_r
readfile
,passthru
,flush
,imagepng
,imagejpeg
무엇보다도 사용자 정의 함수.
- 원시 HTML 영역
.php
파일의 구문 분석되지 않은 HTML 섹션도 직접 출력됩니다. 트리거한다 스크립트 조건header()
호출은 원시 전에 유의해야<html>
블록.
템플릿 체계를 사용하여 출력 논리에서 처리를 분리합니다.<!DOCTYPE html> <?php // Too late for headers already.
- 스크립트 위에 양식 처리 코드를 배치합니다.
- 임시 문자열 변수를 사용하여 메시지를 연기하십시오.
- 실제 출력 로직과 혼합 된 HTML 출력은 마지막에 따라야합니다.
- "script.php line 1 "경고에
<?php
앞의 공백경고가 출력 인라인1
<?php
토큰 앞에 대부분 공백 , 텍스트 또는 HTML이 표시됩니다.
마찬가지로 추가 된 스크립트 또는 스크립트 섹션에서도 발생할 수 있습니다.<?php # There's a SINGLE space/newline before <? - Which already seals it.
PHP는 실제로 태그 닫기 후 한 줄 바꿈을 먹습니다. 그러나 여러 줄 바꿈이나 탭 또는 이러한 간격으로 이동 한 공백을 보상하지는 않습니다.?> <?php
- UTF-8 BOM줄 바꿈과 공백만으로도 문제가 될 수 있습니다. 그러나이를 유발할 수있는 "보이지 않는"문자 시퀀스도 있습니다. 가장 유명한 것은 대부분의 텍스트 편집기에서 표시되지 않는 UTF-8 BOM (Byte-Order-Mark)입니다. UTF-8 인코딩 문서의 경우 선택 사항이며 중복되는 바이트 시퀀스
EF BB BF
그러나 PHP는이를 원시 출력으로 처리해야합니다. 출력에서 문자
(클라이언트가 문서를 Latin-1로 해석하는 경우) 또는 유사한 "쓰레기"로 표시 될 수 있습니다. 특히 그래픽 편집기와 Java 기반 IDE는 그 존재를 알지 못합니다. 그들은 그것을 시각화하지 않습니다 (유니 코드 표준에 의해 의무화 됨). 그러나 대부분의 프로그래머 및 콘솔 편집기는 다음을 수행합니다. 초기에 문제를 쉽게 인식 할 수 있습니다. 다른 편집자는 파일 / 설정 메뉴에서 자신의 존재를 식별 할 수 있습니다 (Windows의 메모장 ++ 는 문제를 식별하고 해결할 수 있음). BOM 존재를 검사하는 또 다른 옵션은 hexeditor 를 사용하는 것입니다. * nix 시스템에서hexdump
는 일반적으로 다음과 같은 문제 및 기타 문제 감사를 단순화하는 그래픽 변형이 아닌 경우 사용할 수 있습니다. 쉬운 수정은 파일을 "UTF-8 (BOM 없음)"또는 이와 유사한 명명법으로 저장하도록 텍스트 편집기를 설정하는 것입니다. 종종 신규 이민자는 새 파일을 만들고 이전 코드를 다시 복사하여 붙여 넣는 방법에 의존합니다.수정 유틸리티sed
/awk
또는recode
)을 검사하고 다시 작성하는 자동화 도구도 있습니다. 특히 PHP의 경우phptags
태그 tidier가 있습니다. 닫기 및 열기 태그를 길고 짧은 형식으로 다시 작성하지만 선행 및 후행 공백, 유니 코드 및 UTF-x BOM 문제도 쉽게 수정합니다.
전체 include 또는 프로젝트 디렉토리에서 사용하는 것이 안전합니다.phptags --whitespace *.php
?>
뒤에 공백닫는?>
뒤에 오류 소스가 언급되면 여기에 공백이나 원시 텍스트가 기록됩니다. PHP 종료 마커는이 시점에서 스크립트 실행을 종료하지 않습니다. 이후의 모든 텍스트 / 공백 문자는 여전히 페이지 콘텐츠로 기록됩니다. 특히 신규 이민자에게는 후행?>
PHP 닫기 태그를 생략해야한다는 것이 일반적으로 권장됩니다. 이것은 이러한 경우의 작은 부분을 피합니다. (일반적으로include()d
스크립트가 범인입니다.)- "0 행에서 알 수 없음"으로 언급 된 오류 소스오류 소스가 구체화되지 않은 경우 일반적으로 PHP 확장 또는 php.ini 설정입니다.
- 때때로
gzip
스트림 인코딩 설정 또는ob_gzhandler
입니다. - 그러나 암시 적 PHP 시작 / 경고 메시지를 생성하는 이중로드 된
extension=
- 때때로
- 선행 오류 메시지다른 PHP 문이나 표현식으로 인해 경고 메시지 나 알림이 출력되는 경우에도 조기 출력으로 간주됩니다. 이 경우 나중에 디버깅을 방해하지 않는 경우 오류를 피하거나, 명령문 실행을 지연하거나, 예를 들어
isset()
또는@()
No error message
php.ini
error_reporting
또는 display_errors
비활성화 된 경우 경고가 표시되지 않습니다. 그러나 오류를 무시한다고해서 문제가 해결되는 것은 아닙니다. 조기 출력 후에도 헤더를 보낼 수 없습니다.
따라서 header("Location: ...")
리디렉션이 자동으로 실패하면 경고를 조사하는 것이 좋습니다. 호출 스크립트 위에 두 개의 간단한 명령을 사용하여 다시 활성화하십시오.
error_reporting(E_ALL);
ini_set("display_errors", 1);
또는 set_error_handler("var_dump");
다른 모든 것이 실패하면.
리디렉션 헤더의 경우 최종 코드 경로에 다음과 같은 관용구를 사용해야하는 경우가 많습니다.
exit(header("Location: /finished.html"));
header()
오류의 경우 사용자 메시지를 인쇄하는 유틸리티 함수도 있습니다.
PHP 출력 버퍼링 은이 문제를 완화하기위한 해결 방법입니다. 종종 안정적으로 작동하지만 적절한 애플리케이션 구조화를 대체하고 제어 로직에서 출력을 분리해서는 안됩니다. 실제 목적은 웹 서버로의 청크 전송을 최소화하는 것입니다.
output_buffering=
설정이 도움이 될 수 있습니다. 최신 FPM / FastCGI 설정 에서 php.ini 또는 .htaccess 또는 .user.ini 를 통해 구성하십시오.
활성화하면 PHP가 출력을 웹 서버로 즉시 전달하는 대신 버퍼링 할 수 있습니다. 따라서 PHP는 HTTP 헤더를 집계 할 수 있습니다.ob_start();
대한 호출에 참여할 수 있습니다. 호출 스크립트 위에. 그러나 여러 가지 이유로 신뢰성이 떨어집니다.<?php ob_start(); ?>
첫 번째 스크립트를 시작합니다. 공백이나 BOM이 이전에 섞여서 비효율적 일 수 있습니다.- HTML 출력을 위해 공백을 숨길 수 있습니다. 그러나 애플리케이션 로직이 바이너리 콘텐츠 (예 : 생성 된 이미지)를 보내려고하면 버퍼링 된 외부 출력이 문제가됩니다. (추가 해결 방법으로
ob_clean()
필요합니다.) - 버퍼는 크기가 제한되어 있으며 기본값으로두면 쉽게 오버런 될 수 있습니다. 그리고 그것은 드물게 발생하지 않으며, 그것이 발생했을 때 추적하기가 어렵습니다.
따라서 두 가지 방법 모두 신뢰할 수 없게 될 수 있습니다. 특히 개발 설정 및 / 또는 프로덕션 서버간에 전환 할 때 더욱 그렇습니다. 그렇기 때문에 출력 버퍼링이 단순한 문제 / 엄격한 해결 방법으로 널리 간주됩니다.
매뉴얼의 기본 사용 예제 와 더 많은 장단점을 참조하십시오.
- 출력 버퍼링이란 무엇입니까?
- PHP에서 출력 버퍼링을 사용하는 이유는 무엇입니까?
- 출력 버퍼링을 사용하는 것이 나쁜 습관으로 간주됩니까?
- "이미 전송 된 헤더"에 대한 올바른 솔루션으로 출력 버퍼링 사용 사례
이전에 헤더 경고를받지 못했다면 출력 버퍼링 php.ini 설정 이 변경된 것입니다. 현재 / 새 서버에서 구성되지 않은 것 같습니다.
항상 headers_sent()
를 사용하여 헤더를 보낼 수 있는지 여부를 조사 할 수 있습니다. 정보를 조건부로 인쇄하거나 다른 대체 논리를 적용하는 데 유용합니다.
if (headers_sent()) {
die("Redirect failed. Please click on this link: <a href=...>");
}
else{
exit(header("Location: /user.php"));
}
유용한 대체 해결 방법은 다음과 같습니다.
- HTML
<meta>
태그- 애플리케이션이 구조적으로 수정하기 어려운 경우 리디렉션을 허용하는 쉬운 (그러나 다소 비전문적 인) 방법은 HTML
<meta>
태그를 삽입하는 것입니다. 리디렉션은 다음을 통해 수행 할 수 있습니다.
또는 짧은 지연으로 :<meta http-equiv="Location" content="http://example.com/">
<meta http-equiv="Refresh" content="2; url=../target.html">
<head>
섹션을지나 사용하면 잘못된 HTML이 생성됩니다. 대부분의 브라우저는 여전히 그것을 받아들입니다.
- 애플리케이션이 구조적으로 수정하기 어려운 경우 리디렉션을 허용하는 쉬운 (그러나 다소 비전문적 인) 방법은 HTML
- 자바 스크립트 리디렉션
- 대안으로 자바 스크립트 리디렉션 을 페이지 리디렉션에 사용할 수 있습니다.
<script> location.replace("target.html"); </script>
<meta>
해결 방법보다 HTML을 더 많이 준수하지만 JavaScript 가능 클라이언트에 의존합니다.
- 대안으로 자바 스크립트 리디렉션 을 페이지 리디렉션에 사용할 수 있습니다.
그러나 두 방법 모두 진짜 HTTP header () 호출이 실패 할 때 허용 가능한 폴백을 만듭니다. 이상적으로는이를 최후의 수단으로 항상 사용자 친화적 인 메시지 및 클릭 가능한 링크와 결합하는 것이 좋습니다. (예를 들어 http_redirect () PECL 확장이 수행하는 작업입니다.)
setcookie() 와 session_start() 도 영향을 받는 이유
setcookie()
와 session_start()
모두 Set-Cookie:
HTTP 헤더를 보내야합니다. 따라서 동일한 조건이 적용되며 조기 출력 상황에 대해 유사한 오류 메시지가 생성됩니다.
(물론 브라우저에서 비활성화 된 쿠키 나 프록시 문제의 영향을받습니다. 세션 기능은 디스크 여유 공간 및 기타 php.ini 설정 등에 따라 달라집니다.)
- Google은 유사한 토론의 긴 목록을 제공합니다.
- 물론 많은 특정 사례 도 Stack Overflow에서 다루었습니다.
- WordPress FAQ는 헤더가 이미 전송 된 경고 문제를 어떻게 해결합니까? 일반적인 방식으로.
- Adobe 커뮤니티 : PHP 개발 : 리디렉션이 작동하지 않는 이유 (헤더가 이미 전송 됨)
- Nucleus FAQ : "이미 보낸 페이지 헤더"는 무엇을 의미합니까?
- 보다 철저한 설명 중 하나는 HTTP 헤더와 PHP header () 함수-NicholasSolutions의 튜토리얼 (인터넷 아카이브 링크)입니다. HTTP를 자세히 다루고 스크립트 재 작성에 대한 몇 가지 지침을 제공합니다.
출처 : https://stackoverflow.com/questions/8028957/how-to-fix-headers-already-sent-error-in-php
'프로그래밍 언어 > PHP' 카테고리의 다른 글
PHP 배열이 연관 또는 순차적인지 확인하는 방법 (0) | 2021.07.21 |
---|---|
PHP에서 주어진 키의 값으로 연관 배열의 배열을 정렬하는 방법 (0) | 2021.07.21 |
command line에서 사용하는 php.ini 파일을 찾는 방법 (0) | 2021.07.20 |
PHP에서 날짜 형식 변환 (0) | 2021.07.20 |
PHP 암호를위한 보안 해시 및 솔트 (0) | 2021.07.20 |