[php] PHP에서“Header already sent”오류를 수정하는 방법

스크립트를 실행할 때 다음과 같은 몇 가지 오류가 발생합니다.

경고 : 헤더 정보를 수정할 수 없습니다 – 이미 (가 보낸 헤더 /some/file.php:12에서 시작 출력 에) /some/file.php라인 (23)

오류 메시지에 언급 된 행은 header()setcookie()호출을 포함 합니다.

그 이유는 무엇입니까? 그리고 그것을 고치는 방법?



답변

헤더를 보내기 전에 출력이 없습니다!

HTTP 헤더를 전송 / 수정하는 기능은 출력하기 전에 호출해야합니다 .
summary ⇊
그렇지 않으면 호출이 실패합니다.

경고 : 헤더 정보를 수정할 수 없습니다-헤더가 이미 전송되었습니다 ( 스크립트 에서 출력이 시작되었습니다 : line )

HTTP 헤더를 수정하는 일부 기능은 다음과 같습니다.

출력은 다음과 같습니다.

  • 의도적 :

    • print, echo및 기타 기능의 제조 출력
    • 원시 <html>섹션 이전 <?php코드.

왜 그런가요?

출력 전에 헤더를 보내야하는 이유를 이해하려면 일반적인 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가 제 1 출력을 수신하면 ( print, echo, <html>)는 것이다
플러시 모든 수집 헤더. 나중에 원하는 모든 출력을 보낼 수 있습니다. 그러나 추가 HTTP 헤더를 보내는 것은 불가능합니다.

조기 출력이 발생한 위치를 어떻게 알 수 있습니까?

header()경고는 문제의 원인을 찾기 위해 모든 관련 정보를 포함합니다 :

경고 : 헤더 정보를 수정할 수 없습니다 – 헤더가 이미 의해 전송
(에서 시작 출력 / www /에서 usr2345 / htdocs에 / auth.php : 52 ) 라인 (100)에 /www/usr2345/htdocs/index.php에서

여기서 “라인 100″은 header() 호출이 실패한 스크립트를 나타냅니다 .

괄호 안에 있는시작에서출력 이 더 중요합니다. 이전 출력의 소스를 나타냅니다. 이 예는의 auth.php
52 . 여기서 조기 출력을 찾아야했습니다.

일반적인 원인 :

  1. 인쇄, 에코

    의도적 인 출력 printecho명령문은 HTTP 헤더 전송 기회를 종료합니다. 이를 방지하려면 애플리케이션 플로우를 재구성해야합니다. 함수
    와 템플릿 구성표를 사용하십시오 . 메시지가 작성 되기 전에header() 통화가 발생 하는지 확인하십시오 .

    출력을 생성하는 기능은 다음과 같습니다.

    • print, echo, printf,vprintf
    • trigger_error, ob_flush, ob_end_flush, var_dump,print_r
    • readfile, passthru, flush, imagepng,imagejpeg

    무엇보다도 사용자 정의 함수.

  2. 원시 HTML 영역

    .php파일의 구문 분석되지 않은 HTML 섹션 도 직접 출력됩니다. 트리거됩니다 스크립트 조건을 header()호출하기 전에주의해야 어떤 원시 <html>블록.

    <!DOCTYPE html>
    <?php
        // Too late for headers already.

    템플릿 구성표를 사용하여 처리를 출력 논리와 분리하십시오.

    • 스크립트 위에 양식 처리 코드를 배치하십시오.
    • 임시 문자열 변수를 사용하여 메시지를 연기하십시오.
    • 실제 출력 로직과 혼합 된 HTML 출력이 마지막에옵니다.
  3. <?php“script.php line 1 “경고 앞의 공백

    경고가 행의 출력을 나타내는 경우 여는 토큰 1앞의 공백 , 텍스트 또는 HTML 이 주로 선행 <?php합니다.

     <?php
    # There's a SINGLE space/newline before <? - Which already seals it.

    마찬가지로 추가 된 스크립트 또는 스크립트 섹션에서도 발생할 수 있습니다.

    ?>
    
    <?php

    PHP는 실제로 태그를 닫은 후 단일 줄 바꿈을 사용합니다. 그러나 여러 줄 바꿈이나 탭 또는 공백이 이러한 간격으로 이동하면 보상되지 않습니다.

  4. UTF-8 BOM

    줄 바꿈과 공백 만 문제가 될 수 있습니다. 그러나 이로 인해 “보이지 않는”문자 시퀀스도 있습니다. 대부분의
    텍스트 편집기에서 표시되지 않는 UTF-8 BOM (Byte-Order-Mark) 이 가장 유명합니다
    . EF BB BFUTF-8로 인코딩 된 문서에는 옵션이며 중복되는 바이트 시퀀스 입니다. 그러나 PHP는이를 원시 출력으로 취급해야합니다. 출력 에서 문자 (클라이언트가 문서를 Latin-1로 해석하는 경우) 또는 유사한 “쓰레기”로 표시 될 수 있습니다.

    특히 그래픽 편집기와 Java 기반 IDE는 존재하지 않습니다. 그들은 그것을 시각화하지 않습니다 (유니 코드 표준에 의해 의무화 됨). 그러나 대부분의 프로그래머와 콘솔 편집기는 다음을 수행합니다.

    UTF-8 BOM 자리 표시 자와 MC 편집기에 점을 표시하는 joes 편집기

    초기에 문제를 쉽게 식별 할 수 있습니다. 다른 편집기는 파일 / 설정 메뉴에서 해당 존재를 식별 할 수 있습니다 (Windows의 메모장 ++에서 문제점을 식별하고 해결할 수 있음
    ). BOM 존재를 검사하는 또 다른 옵션은 hexeditor 를 사용하는 것 입니다. * nix 시스템 hexdump은 일반적으로 이러한 변형 및 기타 문제 감사를 단순화하는 그래픽 변형이 아닌 경우에 사용 가능합니다.

    utf-8 bom을 보여주는 beav hexeditor

    쉬운 수정 방법은 파일을 “UTF-8 (BOM 없음)”또는 이와 유사한 명명법으로 저장하도록 텍스트 편집기를 설정하는 것입니다. 그렇지 않은 경우 종종 새로운 이민자가 새 파일을 만들고 이전 코드를 복사하여 붙여 넣는 것에 의존합니다.

    수정 유틸리티

    텍스트 파일 ( sed/awk 또는 recode) 을 검사하고 다시 쓰는 자동화 된 도구도 있습니다 . PHP의 경우 구체적으로 phptags태그 tidier가 있습니다. 닫고 열린 태그를 길고 짧은 형식으로 다시 작성하지만 선행 및 후행 공백, 유니 코드 및 UTF-x BOM 문제를 쉽게 수정합니다.

    phptags  --whitespace  *.php

    전체 include 또는 프로젝트 디렉토리에서 사용하는 것이 좋습니다.

  5. 공백 ?>

    오류 소스가 닫힘?> 뒤에 언급 된 경우

    공백 또는 원시 텍스트가 작성된 위치입니다. 이 시점에서 PHP 종료 마커는 스크립트 실행을 종료하지 않습니다. 그 이후의 모든 텍스트 / 공백 문자는 여전히 페이지 내용으로 기록됩니다.

    일반적으로, 특히 새로운 이민자들에게, 후행 ?>PHP 닫기 태그는 생략해야합니다. 이것은 이러한 경우의 작은 부분을 합니다. (일반적으로 include()d스크립트는 범인입니다.)

  6. “0 행에서 알 수 없음”으로 언급 된 오류 소스

    오류 소스가 구체화되지 않은 경우 일반적으로 PHP 확장 또는 php.ini 설정입니다.

    • 때때로 gzip스트림 인코딩 설정
      또는ob_gzhandler 입니다.
    • 그러나 또한 extension=암시 적 PHP 시작 / 경고 메시지를 생성하는 이중로드 모듈 일 수도 있습니다 .
  7. 선행 오류 메시지

    다른 PHP 문장이나 표현으로 경고 메시지 나 통지가 출력되면 조기 출력으로 계산됩니다.

    이 경우 나중에 디버깅을 방해하지 않는 경우 오류를 피하거나 명령문 실행을 지연 시키거나 예를 들어 isset()또는 @()-를 사용 하여 메시지를 억제해야합니다
    .

오류 메시지가 없습니다

를 사용 error_reporting하거나 display_errors사용 중지 php.ini한 경우 경고가 표시되지 않습니다. 그러나 오류를 무시해도 문제가 해결되지는 않습니다. 조기 출력 후에도 헤더를 보낼 수 없습니다.

따라서 header("Location: ...")리디렉션이 자동으로 실패하면 경고를 조사하는 것이 좋습니다. 호출 스크립트 위에 두 가지 간단한 명령으로 다시 활성화하십시오.

error_reporting(E_ALL);
ini_set("display_errors", 1);

또는 set_error_handler("var_dump");다른 모든 것이 실패하면.

리디렉션 헤더에 관해서는 최종 코드 경로에 다음과 같은 관용구를 사용해야합니다.

exit(header("Location: /finished.html"));

header()오류 발생시 사용자 메시지를 인쇄하는 유틸리티 기능이 바람직합니다 .

해결 방법으로 출력 버퍼링

PHP 출력 버퍼링
은이 문제를 완화하는 해결 방법입니다. 종종 안정적으로 작동하지만 제어 논리에서 출력을 구성하고 분리하는 적절한 응용 프로그램을 대신해서는 안됩니다. 실제 목적은 웹 서버로의 청크 전송을 최소화하는 것입니다.

  1. output_buffering=
    설정은 그럼에도 불구하고 도움이 될 수 있습니다. 최신 FPM / FastCGI 설정 에서 php.ini
    또는 .htaccess
    또는 .user.ini 를 통해 구성하십시오 .
    이를 사용하면 PHP가 출력을 웹 서버에 즉시 전달하는 대신 출력을 버퍼링 할 수 있습니다. 따라서 PHP는 HTTP 헤더를 집계 할 수 있습니다.

  2. 마찬가지로 ob_start();
    호출 스크립트를 호출하기위한 호출에 참여할 수 있습니다 . 그러나 여러 가지 이유로 신뢰성이 떨어집니다.

    • <?php ob_start(); ?>첫 번째 스크립트를 시작 하더라도 공백이나 BOM이 전에 섞여서 비효율적 일 수 있습니다.

    • HTML 출력을위한 공백을 숨길 수 있습니다. 그러나 응용 프로그램 논리가 이진 콘텐츠 (예 : 생성 된 이미지)를 보내려고하면 버퍼 외부 출력이 문제가됩니다. ( ob_clean()
      추가 해결 방법이 필요합니다.)

    • 버퍼는 크기가 제한되어 있으며 기본값으로두면 쉽게 오버런 될 수 있습니다. 그리고 그것은 드문 일이 아니며,
      일어날 때 추적하기가 어렵습니다 .

따라서 특히 개발 설정 및 / 또는 프로덕션 서버 간을 전환 할 때 두 방법 모두 신뢰할 수 없게 될 수 있습니다. 출력 버퍼링이 목발 / 엄격히 해결 방법으로 널리 간주되는 이유입니다.

매뉴얼 의 기본 사용법 예제 와 더 많은 장단점을 참조하십시오.

그러나 다른 서버에서 작동했습니다!?

이전에 헤더 경고를받지 못한 경우 출력 버퍼링 php.ini 설정
이 변경되었습니다. 현재 / 새 서버에서 구성 해제되었을 수 있습니다.

확인 headers_sent()

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로 이어집니다 . 대부분의 브라우저는 여전히이를 수락합니다.

  • 자바 스크립트 리디렉션

    대안으로
    페이지 리디렉션에 JavaScript 리디렉션을 사용할 수 있습니다.

     <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 설정 등에 따라 달라집니다)

추가 링크


답변

이 오류 메시지가 트리거됩니다 어떤이 (당신이 HTTP 헤더를 보내기 전에 전송 setcookie또는 header). HTTP 헤더 전에 무언가를 출력하는 일반적인 이유는 다음과 같습니다.

  • 다음과 같이 파일의 시작 또는 끝에 실수로 발생하는 공백 :

     <?php
    // Note the space before "<?php"
    ?>

       이를 피하려면 간단히 닫는 것을 생략하십시오 ?>. 어쨌든 필요하지 않습니다.

  • PHP 파일의 시작 부분에 바이트 순서 표시 . 16 진 편집기로 PHP 파일을 검사하여 해당 여부를 찾으십시오. 바이트로 시작해야합니다 3F 3C. EF BB BF파일 시작 부분에서 BOM 을 안전하게 제거 할 수 있습니다 .
  • 이러한 호출에 대한 명시적인 출력, echo, printf, readfile, passthru, 코드 앞에 <?
  • display_errorsphp.ini 속성이 설정 되면 php에 의해 경고가 출력됩니다 . php는 프로그래머의 실수로 충돌하는 대신 오류를 자동으로 수정하고 경고를 표시합니다. display_errorsor error_reporting 구성을 수정할 수는 있지만 문제를 해결해야합니다.
    일반적인 원인 (예 : 배열의 정의 요소에 액세스되어 $_POST['input']사용하지 않고, empty또는 isset입력이 세트가 있는지 여부를 테스트하는) 또는 (같이 정의되지 않은 정수가 아닌 문자열 상수 값을 이용하여 $_POST[input]손실 된 인용 참고).

출력 버퍼링을 켜면 문제가 해결됩니다. 를 호출 한 후의 모든 출력 ob_start은 버퍼를 해제 할 때까지 (예 : with) 버퍼링됩니다 ob_end_flush.

그러나 출력 버퍼링으로 문제를 피할 수 있지만 애플리케이션이 HTTP 헤더 전에 HTTP 본문을 출력하는 이유를 실제로 판별해야합니다. 전화를 걸고 하루와 날씨를 논의하여 발신자에게 전화 번호가 잘못되었다고 알리는 것과 같습니다.


답변

이 오류가 여러 번 발생했으며 모든 PHP 프로그래머가 적어도 한 번은이 오류가 발생했다고 확신합니다.

가능한 해결책 1

이 오류는 파일 시작 또는 파일 끝 이후 의 공백으로 인해 발생했을 수 있습니다. 이러한 공백은 여기에 없어야합니다.

예) 공백이 없어야합니다

   echo "your code here";

?>
THERE SHOULD BE NO BLANK SPACES HERE

이 오류의 원인이되는 파일과 관련된 모든 파일을 확인하십시오.

참고 : 때때로 gedit (기본 Linux 편집기)와 같은 EDITOR (IDE)는 저장 파일에 빈 줄을 하나 추가합니다. 이런 일은 일어나지 않아야합니다. Linux를 사용중인 경우 VI 편집기를 사용하여 페이지 끝에서?> 뒤에 공백 / 줄을 제거 할 수 있습니다.

가능한 해결 방법 2 :이
경우가 아니면 ob_start 를 사용하여 버퍼링 을 출력하십시오.

<?php
  ob_start();

  // code 

 ob_end_flush();
?> 

출력 버퍼링이 켜지고 페이지가 버퍼링 된 후 헤더가 생성됩니다.


답변

아래 줄 대신

//header("Location:".ADMIN_URL."/index.php");

쓰다

echo("<script>location.href = '".ADMIN_URL."/index.php?msg=$msg';</script>");

또는

?><script><?php echo("location.href = '".ADMIN_URL."/index.php?msg=$msg';");?></script><?php

확실히 문제를 해결할 것입니다. 나는 같은 문제에 직면했지만 위의 방법으로 헤더 위치를 작성하여 해결했습니다.


답변

당신은

printf ("Hi %s,</br />", $name);

쿠키를 설정하기 전에 허용되지 않습니다. 빈 줄이 아니라 헤더 앞에 출력을 보낼 수 없습니다.


답변

이 줄 때문입니다.

printf ("Hi %s,</br />", $name);

헤더를 보내기 전에 어떤 것도 인쇄 / 에코 하지 않아야합니다 .


답변

일반적인 문제 :

( 출처 : source )

====================

1) 명령 echo..이전에 출력 (예 : HTML 코드 ) 이 없어야합니다 header(.......);.

2) 어떤 제거 공백 (또는 줄 바꿈을 하기 전에) <?php후에 ?>태그입니다.

3) 골든 룰! -해당 PHP 파일 (및 include다른 파일도)에 BOM 인코딩이 없는 UTF8이 있는지 확인하십시오 ( UTF-8 뿐만 아니라 ). UTF8로 인코딩 된 파일은 텍스트 파일 편집기에 표시되지 않는 PHP 파일의 시작 부분에 특별한 문자가 있기 때문에 많은 경우에 문제가 있습니다 !!!!!!!!!!!

4)header(...);사용한다exit;

5) 항상 301 또는 302 참조를 사용하십시오.

header("location: http://example.com",  true,  301 );  exit;

6) 오류보고를 켜고 오류를 찾으십시오. 작동하지 않는 기능으로 인해 오류가 발생했을 수 있습니다. 오류보고를 설정하면 항상 최상위 오류를 먼저 수정해야합니다. 예를 들어, “경고 : date_default_timezone_get () : 시스템의 시간대 설정에 의존하는 것은 안전하지 않습니다.” -아래로 내려 갈수록 “헤더가 전송되지 않음”오류가 표시 될 수 있습니다. 최상위 (1 차) 오류를 수정 한 후 페이지를 다시로드하십시오. 여전히 오류가 발생하면 최상위 오류를 다시 수정하십시오.

7) 위의 방법 중 어느 것도 도움이되지 않으면 JAVSCRIPT 리디렉션을 사용하십시오 (그러나 강력하게 권장하지 않는 방법). 맞춤 경우에는 마지막 기회 일 수 있습니다 … :

echo "<script type='text/javascript'>window.top.location='http://website.com/';</script>"; exit;