Làm cách nào để sửa lỗi Tiêu đề đã được gửi lỗi trong PHP trong PHP


831

Khi chạy tập lệnh của tôi, tôi gặp một số lỗi như thế này:

Cảnh báo: Không thể sửa đổi thông tin tiêu đề - các tiêu đề đã được gửi bởi ( đầu ra bắt đầu tại /some/file.php:12 ) trong /some/file.php trên dòng 23

Các dòng được đề cập trong thông báo lỗi chứa header()setcookie()các cuộc gọi.

Điều gì có thể là lý do cho điều này? Và làm thế nào để khắc phục nó?



Hãy chắc chắn rằng không có văn bản nào được xuất ra ( ob_startob_end_clean() có thể chứng minh hữu ích ở đây). Sau đó, bạn có thể đặt cookie hoặc phiên bằng ob_get_contents()và sau đó sử dụng ob_end_clean()để xóa bộ đệm.
Jack Tuck

Sử dụng safeRedirecthàm trong Thư viện PHP của tôi: github.com/heinkasner/PHP-L
Library / blob / master / textra.php

5
~~~~~~~~~ ~ Tập tin của bạn ENCODING không nên UTF-8, nhưng UTF-8 (Without BOM)~~~~~~~~~~~
T.Todua

Câu trả lời:


2997

Không có đầu ra trước khi gửi tiêu đề!

Các chức năng gửi / sửa đổi các tiêu đề HTTP phải được gọi trước khi bất kỳ đầu ra nào được thực hiện . summary ⇊ Nếu không, cuộc gọi thất bại:

Cảnh báo: Không thể sửa đổi thông tin tiêu đề - các tiêu đề đã được gửi (đầu ra bắt đầu tại script: line )

Một số chức năng sửa đổi tiêu đề HTTP là:

Đầu ra có thể là:

  • Vô tình:

    • Khoảng trắng trước <?phphoặc sau?>
    • Các UTF-8 Byte Order Mark đặc biệt
    • Thông báo lỗi hoặc thông báo trước
  • Cố ý:

    • print, echoVà các chức năng khác sản xuất ra
    • Phần thô mã <html>trước <?php.

Tại sao nó xảy ra?

Để hiểu lý do tại sao các tiêu đề phải được gửi trước khi xuất, cần phải xem phản hồi HTTP thông thường . Các tập lệnh PHP chủ yếu tạo nội dung HTML, nhưng cũng chuyển một bộ tiêu đề HTTP / CGI cho máy chủ web:

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>

Trang / đầu ra luôn theo sau các tiêu đề. PHP phải chuyển các tiêu đề đến máy chủ web trước. Nó chỉ có thể làm điều đó một lần. Sau khi phá vỡ dòng đôi, nó không bao giờ có thể sửa đổi chúng.

Khi PHP nhận ra đầu tiên ( print, echo, <html>) nó sẽ tuôn tất cả các tiêu đề thu thập được. Sau đó, nó có thể gửi tất cả đầu ra mà nó muốn. Nhưng việc gửi thêm các tiêu đề HTTP là không thể.

Làm thế nào bạn có thể tìm ra nơi đầu ra sớm xảy ra?

Các header()cảnh báo có chứa tất cả các thông tin liên quan để xác định vấn đề nguyên nhân:

Cảnh báo: Không thể sửa đổi thông tin tiêu đề - các tiêu đề đã được gửi bởi (đầu ra bắt đầu tại / www / usr2345 / htdocs / auth.php: 52 ) trong /www/usr2345/htdocs/index.php trên dòng 100

Ở đây "dòng 100" đề cập đến kịch bản mà lệnh header() gọi không thành công.

Ghi chú " đầu ra bắt đầu tại " trong ngoặc đơn có ý nghĩa hơn. Nó biểu thị nguồn của đầu ra trước đó. Trong ví dụ này, nó auth.phpdòng52 . Đó là nơi bạn phải tìm kiếm đầu ra sớm.

Nguyên nhân điển hình:

  1. In, tiếng vang

    Đầu ra có chủ ý từ printvà các echocâu lệnh sẽ chấm dứt cơ hội gửi các tiêu đề HTTP. Luồng ứng dụng phải được cơ cấu lại để tránh điều đó. Sử dụng các chức năng và sơ đồ khuôn mẫu. Đảm bảo header()cuộc gọi xảy ra trước khi tin nhắn được viết ra.

    Các hàm tạo ra đầu ra bao gồm

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


    trong số những người khác và các chức năng do người dùng định nghĩa.

  2. Khu vực HTML thô

    Các phần HTML chưa được chỉnh sửa trong một .phptệp cũng là đầu ra trực tiếp. Các điều kiện tập lệnh sẽ kích hoạt một header()cuộc gọi phải được lưu ý trước bất kỳ<html> khối thô nào .

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

    Sử dụng sơ đồ tạo khuôn mẫu để tách xử lý khỏi logic đầu ra.

    • Đặt mã xử lý biểu mẫu trên kịch bản.
    • Sử dụng các biến chuỗi tạm thời để trì hoãn tin nhắn.
    • Logic đầu ra thực tế và đầu ra HTML xen kẽ nên theo sau.

  3. Khoảng trắng trước <?phpcho cảnh báo "script.php dòng 1 "

    Nếu cảnh báo đề cập đến đầu ra theo dòng 1, thì đó chủ yếu là khoảng trắng , văn bản hoặc HTML trước <?phpmã thông báo mở .

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

    Tương tự, nó có thể xảy ra đối với các đoạn script được nối thêm hoặc các đoạn script:

    ?>
    
    <?php

    PHP thực sự ăn lên một đơn linebreak sau thẻ đóng. Nhưng nó sẽ không bù nhiều dòng mới hoặc tab hoặc khoảng trắng được chuyển vào những khoảng trống như vậy.

  4. UTF-8 BOM

    Linebreaks và không gian một mình có thể là một vấn đề. Nhưng cũng có những chuỗi nhân vật "vô hình" có thể gây ra điều này. Nổi tiếng nhất là BOM UTF-8 (Byte-Order-Mark) không được hiển thị bởi hầu hết các trình soạn thảo văn bản. Đó là chuỗi byte EF BB BF, là tùy chọn và dự phòng cho các tài liệu được mã hóa UTF-8. PHP tuy nhiên phải coi nó là đầu ra thô. Nó có thể hiển thị dưới dạng các ký tự trong đầu ra (nếu máy khách diễn giải tài liệu là Latin-1) hoặc "rác" tương tự.

    Trong các trình soạn thảo đồ họa cụ thể và các IDE dựa trên Java không biết đến sự hiện diện của nó. Họ không hình dung nó (bắt buộc theo tiêu chuẩn Unicode). Tuy nhiên, hầu hết các biên tập viên lập trình và giao diện điều khiển đều làm:

    trình chỉnh sửa joes hiển thị trình giữ chỗ UTF-8 BOM và trình soạn thảo MC một dấu chấm

    Có dễ dàng nhận ra vấn đề sớm. Các biên tập viên khác có thể xác định sự hiện diện của nó trong menu tệp / cài đặt (Notepad ++ trên Windows có thể xác định và khắc phục sự cố ), Một tùy chọn khác để kiểm tra sự hiện diện của BOM là dùng đến một hexeditor . Trên các hệ thống * nix hexdumpthường có sẵn, nếu không phải là một biến thể đồ họa giúp đơn giản hóa việc kiểm tra những vấn đề này và các vấn đề khác:

    beav hexeditor hiển thị bom utf-8

    Một cách khắc phục dễ dàng là đặt trình soạn thảo văn bản để lưu tệp dưới dạng "UTF-8 (không có BOM)" hoặc danh pháp tương tự như vậy. Thường thì những người mới sử dụng để tạo các tệp mới và chỉ cần sao chép và dán mã trước đó vào lại.

    Tiện ích sửa chữa

    Ngoài ra còn có các công cụ tự động để kiểm tra và viết lại các tệp văn bản ( sed/awk hoặc recode). Đối với PHP cụ thể có phptagsthẻ tidier . Nó viết lại các thẻ đóng và mở thành các dạng dài và ngắn, nhưng cũng dễ dàng sửa các khoảng trắng hàng đầu và dấu, các vấn đề BOM Unicode và UTF-x:

    phptags  --whitespace  *.php

    Thật tuyệt vời khi sử dụng trên toàn bộ thư mục bao gồm hoặc dự án.

  5. Khoảng trắng sau ?>

    Nếu nguồn lỗi được đề cập là đằng sau việc đóng?> thì đây là nơi một số khoảng trắng hoặc văn bản thô được viết ra. Điểm đánh dấu kết thúc PHP không chấm dứt thực thi tập lệnh tại thời điểm này. Bất kỳ ký tự văn bản / dấu cách nào sau nó sẽ được viết dưới dạng nội dung trang.

    Đặc biệt, thông thường, đối với những người mới sử dụng, ?>nên bỏ qua các thẻ đóng PHP kéo dài . Điều này tránh một phần nhỏ của những trường hợp này. (Khá thường include()dcác kịch bản là thủ phạm.)

  6. Nguồn lỗi được đề cập là "Không xác định trên dòng 0"

    Đó thường là phần mở rộng PHP hoặc cài đặt php.ini nếu không có nguồn lỗi nào được cụ thể hóa.

    • Thỉnh thoảng, gzipcài đặt mã hóa luồng hoặcob_gzhandler .
    • Nhưng nó cũng có thể là bất kỳ extension=mô-đun được tải gấp đôi nào tạo ra một thông báo khởi động / cảnh báo PHP ẩn.

  7. Thông báo lỗi trước

    Nếu một câu lệnh hoặc biểu thức PHP khác gây ra một thông báo cảnh báo hoặc thông báo được in ra, thì đó cũng được tính là đầu ra sớm.

    Trong trường hợp này, bạn cần tránh lỗi, trì hoãn thực thi câu lệnh hoặc chặn thông báo bằng vd isset() hoặc @()- khi không cản trở việc gỡ lỗi sau này.

Không có thông báo lỗi

Nếu bạn có error_reporting hoặc display_errorsbị vô hiệu hóa php.ini, thì sẽ không có cảnh báo nào xuất hiện. Nhưng bỏ qua lỗi sẽ không làm cho vấn đề biến mất. Tiêu đề vẫn không thể được gửi sau khi đầu ra sớm.

Vậy khi nào header("Location: ...") chuyển hướng âm thầm thất bại, rất nên thăm dò các cảnh báo. Reenable chúng với hai lệnh đơn giản trên đỉnh kịch bản lệnh:

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

Hoặc set_error_handler("var_dump");nếu tất cả những thứ khác đều thất bại.

Nói về tiêu đề chuyển hướng, bạn thường nên sử dụng một thành ngữ như thế này cho các đường dẫn mã cuối cùng:

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

Tốt nhất là ngay cả một chức năng tiện ích, trong đó in một tin nhắn người dùng trong trường hợp header() thất bại.

Bộ đệm đầu ra như cách giải quyết

Bộ đệm đầu ra của PHP là một cách giải quyết để giảm bớt vấn đề này. Nó thường hoạt động đáng tin cậy, nhưng không nên thay thế cho cấu trúc ứng dụng phù hợp và tách đầu ra khỏi logic điều khiển. Mục đích thực tế của nó là giảm thiểu chuyển giao chunked đến máy chủ web.

  1. Các output_buffering= thiết lập tuy nhiên có thể giúp đỡ. Định cấu hình nó trong php.ini hoặc thông qua .htaccess hoặc thậm chí .user.ini trên các thiết lập FPM / FastCGI hiện đại.
    Kích hoạt nó sẽ cho phép PHP đệm đầu ra thay vì chuyển nó đến máy chủ web ngay lập tức. Do đó, PHP có thể tổng hợp các tiêu đề HTTP.

  2. Nó cũng có thể được tham gia với một cuộc gọi để ob_start(); ở trên kịch bản lệnh gọi. Tuy nhiên, điều này ít đáng tin cậy hơn vì nhiều lý do:

    • Ngay cả khi <?php ob_start(); ?>bắt đầu tập lệnh đầu tiên, khoảng trắng hoặc BOM có thể bị xáo trộn trước đó, khiến nó không hiệu quả .

    • Nó có thể che giấu khoảng trắng cho đầu ra HTML. Nhưng ngay khi logic ứng dụng cố gắng gửi nội dung nhị phân (ví dụ hình ảnh được tạo), đầu ra bên ngoài được đệm trở thành một vấn đề. (Cần thiết ob_clean() như cách giải quyết xa hơn.)

    • Bộ đệm bị giới hạn về kích thước và có thể dễ dàng tràn ngập khi để mặc định. Và đó cũng không phải là chuyện hiếm gặp, khó theo dõi khi nó xảy ra.

Do đó, cả hai phương pháp đều có thể trở nên không đáng tin cậy - đặc biệt khi chuyển đổi giữa các thiết lập phát triển và / hoặc máy chủ sản xuất. Đó là lý do tại sao bộ đệm đầu ra được coi rộng rãi chỉ là một cái nạng / đúng là một cách giải quyết.

Xem thêm ví dụ sử dụng cơ bản trong hướng dẫn và để biết thêm ưu và nhược điểm:

Nhưng nó hoạt động trên máy chủ khác!?

Nếu bạn không nhận được cảnh báo tiêu đề trước đó, thì cài đặt php.ini đệm đầu ra đã thay đổi. Có thể nó chưa được định cấu hình trên máy chủ hiện tại / mới.

Kiểm tra với headers_sent()

Bạn luôn có thể sử dụng headers_sent()để thăm dò nếu vẫn có thể ... gửi tiêu đề. Điều này hữu ích để in một cách có điều kiện một thông tin hoặc áp dụng logic dự phòng khác.

if (headers_sent()) {
    die("Redirect failed. Please click on this link: <a href=...>");
}
else{
    exit(header("Location: /user.php"));
}

Giải pháp dự phòng hữu ích là:

  • <meta>Thẻ HTML

    Nếu ứng dụng của bạn có cấu trúc khó sửa, thì một cách dễ dàng (nhưng hơi không chuyên nghiệp) để cho phép chuyển hướng là tiêm <meta>thẻ HTML . Một chuyển hướng có thể đạt được với:

     <meta http-equiv="Location" content="http://example.com/">

    Hoặc với một độ trễ ngắn:

     <meta http-equiv="Refresh" content="2; url=../target.html">

    Điều này dẫn đến HTML không hợp lệ khi được sử dụng qua <head>phần. Hầu hết các trình duyệt vẫn chấp nhận nó.

  • Chuyển hướng JavaScript

    Thay thế, một chuyển hướng JavaScript có thể được sử dụng cho các chuyển hướng trang:

     <script> location.replace("target.html"); </script>

    Mặc dù điều này thường tuân thủ HTML nhiều hơn so với <meta>cách giải quyết, nhưng nó phát sinh sự phụ thuộc vào các máy khách có khả năng JavaScript.

Tuy nhiên, cả hai cách tiếp cận đều tạo ra các dự phòng chấp nhận được khi các cuộc gọi tiêu đề HTTP () chính hãng không thành công. Lý tưởng nhất là bạn luôn kết hợp điều này với một tin nhắn thân thiện với người dùng và liên kết có thể nhấp như là phương sách cuối cùng. (Ví dụ, phần mở rộng PECL của http_redirect () làm gì.)

Tại sao setcookie()session_start()cũng bị ảnh hưởng

Cả hai setcookie()session_start()cần phải gửi một Set-Cookie:tiêu đề HTTP. Do đó, các điều kiện tương tự được áp dụng và các thông báo lỗi tương tự sẽ được tạo cho các tình huống đầu ra sớm.

(Tất nhiên chúng bị ảnh hưởng nhiều hơn bởi các cookie bị vô hiệu hóa trong trình duyệt hoặc thậm chí các sự cố proxy. Chức năng phiên rõ ràng cũng phụ thuộc vào dung lượng đĩa trống và các cài đặt php.ini khác, v.v.)

Liên kết khác


Ngoài ra notepad.exe thông thường là khó khăn. Tôi thường sử dụng NetBeans mà không thêm BOM, ngay cả khi tệp được mã hóa như vậy. Chỉnh sửa một tệp sau này trong notepad làm rối tung mọi thứ, đặc biệt là đối với IIS là máy chủ web. Có vẻ như apache loại bỏ BOM (được thêm vào một cách có chủ ý).
Teson

4
Loại bỏ việc đóng ?>từ cuối tệp php thường là một cách thực hành tốt giúp giảm thiểu các lỗi này. Khoảng trắng không mong muốn sẽ không xuất hiện ở cuối tệp và bạn vẫn có thể thêm tiêu đề vào phản hồi sau. Nó cũng thuận tiện nếu bạn sử dụng bộ đệm đầu ra và không muốn thấy khoảng trắng không mong muốn được thêm vào cuối các phần được tạo bởi các tệp được bao gồm.
Nikita 8/2/2016

Điều kỳ lạ, tôi đã chuyển tập tin của mình từ cPanel Linux Hosting sang VPS. Trước khi nó hoạt động đúng nhưng ở đây nó đã hiển thị lỗi này. (Tôi đã có một số mã html trước tiêu đề). Tại sao?
Pablo Escobar

@Purushotamrawat Bạn đã đọc phần về " Nhưng nó hoạt động trên máy chủ khác!? "
mario

1
@PeterSMcIntyre BOM UTF8 có lẽ (sửa lỗi đó) / không bật bộ đệm đầu ra (không dựa vào điều đó).
mario

199

Thông báo lỗi này được kích hoạt khi bất cứ điều gì được gửi trước khi bạn gửi tiêu đề HTTP (có setcookiehoặc header). Các lý do phổ biến để xuất ra một cái gì đó trước các tiêu đề HTTP là:

  • Khoảng trắng ngẫu nhiên, thường ở đầu hoặc cuối tệp, như thế này:

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

       Để tránh điều này, chỉ cần bỏ qua việc đóng cửa ?>- dù sao cũng không bắt buộc.

  • Dấu thứ tự byte ở đầu tập tin php. Kiểm tra các tệp php của bạn với trình soạn thảo hex để tìm hiểu xem đó có phải là trường hợp không. Họ nên bắt đầu với các byte 3F 3C. Bạn có thể xóa BOM một cách an toàn EF BB BFtừ đầu tệp.
  • Đầu ra rõ ràng, chẳng hạn như các cuộc gọi đến echo, printf, readfile, passthru, mã trước <?, vv
  • Một cảnh báo được đưa ra bởi php, nếu thuộc tính display_errorsphp.ini được đặt. Thay vì gặp lỗi về lập trình viên, php âm thầm sửa lỗi và phát ra cảnh báo. Trong khi bạn có thể thay đổi display_errorshoặc error_reporting cấu hình, bạn thay vì phải sửa chữa vấn đề.
    Lý do phổ biến là truy cập vào các phần tử không xác định của một mảng (chẳng hạn như $_POST['input']không sử dụng emptyhoặc issetđể kiểm tra xem đầu vào đã được đặt chưa) hoặc sử dụng hằng số không xác định thay vì một chuỗi ký tự (như trong $_POST[input], lưu ý các dấu ngoặc kép bị thiếu).

Bật bộ đệm đầu ra sẽ làm cho vấn đề biến mất; tất cả đầu ra sau khi gọi đến ob_startđược đệm trong bộ nhớ cho đến khi bạn giải phóng bộ đệm, ví dụ như với ob_end_flush.

Tuy nhiên, trong khi bộ đệm đầu ra tránh được các vấn đề, bạn thực sự nên xác định lý do tại sao ứng dụng của bạn xuất ra phần thân HTTP trước tiêu đề HTTP. Điều đó giống như nhận một cuộc gọi điện thoại và thảo luận về ngày của bạn và thời tiết trước khi nói với người gọi rằng anh ta đã nhầm số.


nó giúp tôi cảm ơn
Vishwa Pratap

122

Tôi đã gặp lỗi này nhiều lần trước đây và tôi chắc chắn tất cả các lập trình viên PHP đều gặp lỗi này ít nhất một lần trước đó.

Giải pháp khả thi 1

Lỗi này có thể do các khoảng trắng trước khi bắt đầu tệp hoặc sau khi kết thúc tệp. Các khoảng trống này không nên ở đây.

ví dụ) KHÔNG NÊN KHÔNG CÓ SPACES TẠI ĐÂY

   echo "your code here";

?>
THERE SHOULD BE NO BLANK SPACES HERE

Kiểm tra tất cả các tập tin liên quan đến tập tin gây ra lỗi này.

Lưu ý: Đôi khi EDITOR (IDE) như gedit (trình chỉnh sửa linux mặc định) thêm một dòng trống vào tệp lưu. Điều này không nên xảy ra. Nếu bạn đang sử dụng Linux. bạn có thể sử dụng trình soạn thảo VI để xóa khoảng trắng / dòng sau?> ở cuối trang.

Giải pháp có thể 2: Nếu đây không phải là trường hợp của bạn, thì hãy sử dụng ob_start để xuất bộ đệm:

<?php
  ob_start();

  // code 

 ob_end_flush();
?> 

Điều này sẽ bật bộ đệm đầu ra và các tiêu đề của bạn sẽ được tạo sau khi trang được đệm.


18
ob_start()chỉ che giấu vấn đề; không sử dụng nó để giải quyết vấn đề đặc biệt này
Ja͢ck

@ Ja͢ck Nếu tôi không sử dụng ob_start()thì tôi nên làm gì để giải quyết vấn đề này:Headers already sent
Shafizadeh 14/07/2015

@Sajad nếu bạn gặp lỗi cụ thể do trình chỉnh sửa bạn đang sử dụng, bạn nên tìm hiểu các cài đặt để khiến nó dừng gây ra sự cố hoặc chuyển đổi trình chỉnh sửa. Nếu bạn gặp lỗi vì bất kỳ lý do nào khác, bạn nên đọc qua các câu trả lời trong câu hỏi này (cụ thể là câu trả lời được chấp nhận) để tìm ra vấn đề thực sự là gì và giải quyết nó.
Samsquanch 14/07/2015

3
ob_start()không "che giấu" vấn đề, nó giải quyết vấn đề.
TMS

1
Tôi đã gặp sự cố như vậy khi tải tệp của mình lên máy chủ, hỗ trợ ngay cả PHP5.3 Sử dụng máy chủ có PHP 5.6 trở lên
GGSoft

86

Thay vì dòng dưới đây

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

viết

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

hoặc là

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

Nó chắc chắn sẽ giải quyết vấn đề của bạn. Tôi đã đối mặt với cùng một vấn đề nhưng tôi đã giải quyết thông qua việc viết vị trí tiêu đề theo cách trên.


41

Bạn làm

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

trước khi đặt cookie, không được phép. Bạn không thể gửi bất kỳ đầu ra nào trước các tiêu đề, thậm chí không phải là một dòng trống.


32

Đó là vì dòng này:

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

Bạn không nên in / echo bất cứ điều gì trước khi gửi các tiêu đề.


31

NHỮNG VẤN ĐỀ CHUNG:

(được sao chép từ: nguồn )

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

1) không nên có bất kỳ đầu ra nào (tức là echo..mã HTML) trước header(.......);lệnh.

2) xóa mọi khoảng trắng (hoặc dòng mới ) trước <?phpvà sau ?>thẻ.

3) QUY TẮC VÀNG! - kiểm tra xem tệp php đó (và cả, nếu includecác tệp khác của bạn ) có UTF8 không có mã hóa BOM (và không chỉ UTF-8 ). Đó là vấn đề trong nhiều trường hợp (vì tệp được mã hóa UTF8 có ký tự đặc biệt khi bắt đầu tệp php, trình soạn thảo văn bản của bạn không hiển thị) !!!!!!!!!!!

4) Sau khi header(...);bạn phải sử dụngexit;

5) luôn sử dụng tham chiếu 301 hoặc 302:

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

6) Bật báo cáo lỗi và tìm lỗi. Lỗi của bạn có thể do một chức năng không hoạt động. Khi bạn bật báo cáo lỗi, trước tiên bạn phải luôn sửa lỗi hàng đầu. Ví dụ: nó có thể là "Cảnh báo: date_default_timezone_get (): Không an toàn khi dựa vào cài đặt múi giờ của hệ thống." - sau đó xa hơn bạn có thể thấy lỗi "tiêu đề không được gửi". Sau khi sửa lỗi trên cùng (thứ 1), tải lại trang của bạn. Nếu bạn vẫn có lỗi, thì một lần nữa sửa lỗi trên cùng.

7) Nếu không có cách nào ở trên giúp được, hãy sử dụng chuyển hướng JAVSCRIPT (tuy nhiên, phương pháp không được khuyến nghị mạnh mẽ), có thể là cơ hội cuối cùng trong các trường hợp tùy chỉnh ...:

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

Tại sao rõ ràng là thiết lập 301hoặc 302quan trọng?
Jāni Elmeris

26

Một mẹo đơn giản: Một không gian đơn giản (hoặc char đặc biệt vô hình) trong tập lệnh của bạn, ngay trước <?phpthẻ đầu tiên , có thể gây ra điều này! Đặc biệt là khi bạn đang làm việc trong một nhóm và ai đó đang sử dụng IDE "yếu" hoặc đã làm rối tung các tệp có trình soạn thảo văn bản lạ.

Tôi đã thấy những điều này;)


22

Một thực tiễn xấu khác có thể gọi vấn đề này chưa được nêu.

Xem đoạn mã này:

<?php
include('a_important_file.php'); //really really really bad practise
header("Location:A location");
?>

Mọi thứ đều ổn, phải không?

Điều gì xảy ra nếu "a_important_file.php" là đây:

<?php
//some php code 
//another line of php code
//no line above is generating any output
?>

 ----------This is the end of the an_important_file-------------------

Điều này sẽ không làm việc? Bởi vì đã có một dòng mới được tạo ra.

Bây giờ, mặc dù đây không phải là một kịch bản phổ biến, nếu bạn đang sử dụng khung MVC tải rất nhiều tệp trước khi bàn giao mọi thứ cho bộ điều khiển của bạn thì sao? Đây không phải là một kịch bản hiếm gặp. Hãy chuẩn bị cho việc này.

Từ PSR-2 2.2:


  • Tất cả các tệp PHP PHẢI sử dụng Unix LF (linefeed) line ending.
  • Tất cả các tệp PHP PHẢI kết thúc bằng một single blank line.
  • Thẻ đóng?> PHẢI omittedtừ các tệp có chứaonly php

Tin tôi đi, làm theo tiêu chuẩn của bạn có thể giúp bạn tiết kiệm rất nhiều giờ khỏi cuộc sống của bạn :)


2
Theo một số tiêu chuẩn (ví dụ Zend), bạn không nên đặt ?>thẻ đóng trong bất kỳ tệp nào trong mọi trường hợp
Daniel W.

Tôi không thể tái tạo điều này trong môi trường Windows vì nó hoạt động bằng cách sử dụng bất kỳ kết hợp nào (thêm thẻ đóng, khoảng trống, nhấn phím enter, v.v.). Có vẻ như vấn đề này xảy ra chủ yếu trong môi trường Linux.
Junior Mayhé

@JuniorM Nó có thể được tái sản xuất. Bạn có thể chia sẻ mã mà bạn đã thử nghiệm trong một ý chính hay một cái gì đó giống nhau không?
MD. Sahib Bin Mahboob

Tôi đang dùng Windows 7, đã cài đặt Wamp mới nhất. Tôi nghĩ rằng lỗi này có liên quan đến các ký tự ẩn cho đến cuối dòng. Shortcodes.php của tôi là nguyên nhân gây ra vấn đề. Tôi đã thêm vào tập tin này một chức năng đơn giản và nó bắt đầu thực hiện lỗi "tiêu đề đã gửi" này. Tôi đã so sánh shortcodes.php của mình với wordpress 'và nó vẫn ổn, ngoại trừ CR LF(dòng Windows điển hình). Tôi giải quyết nó bằng cách tải xuống tệp gốc từ reppress Wordpress có LF(dòng cuối Linux) thay vào đó CR LFvà tôi cũng đã chuyển chức năng của mình sang chức năng của theme.php. Dựa trên: bit.ly/1Gh6mzN
Junior Mayhé

@Sahib, lưu ý rằng tôi vẫn không thể sao chép những gì được nêu trong câu trả lời này. Câu trả lời là hoàn toàn tốt cho môi trường Linux. Tôi đã kiểm tra những thứ như một khoảng trống giữa ?> <?php, loại bỏ và thêm một dòng trống đơn, thêm và bỏ qua thẻ đóng ?>. Trong Windows + Wamp tất cả các kết hợp đó hoạt động tốt. Wierd ...
Junior Mayhé

15

Đôi khi, khi quy trình dev có cả trạm làm việc WIN và hệ thống LINUX (lưu trữ) và trong mã bạn không thấy bất kỳ đầu ra nào trước dòng liên quan, đó có thể là định dạng của tệp và thiếu kết thúc dòng Unix LF (linefeed) .

Những gì chúng ta thường làm để nhanh chóng khắc phục điều này, là đổi tên tệp và trên hệ thống LINUX tạo một tệp mới thay vì đổi tên, sau đó sao chép nội dung vào đó. Nhiều lần điều này giải quyết vấn đề vì một số tệp được tạo trong WIN đã chuyển sang lưu trữ gây ra sự cố này.

Khắc phục sự cố này là một sửa chữa dễ dàng cho các trang web chúng tôi quản lý bởi FTP và đôi khi có thể tiết kiệm thời gian cho các thành viên nhóm mới của chúng tôi.


2

Nói chung, lỗi này phát sinh khi chúng tôi gửi tiêu đề sau khi lặp lại hoặc in. Nếu lỗi này phát sinh trên một trang cụ thể thì hãy đảm bảo rằng trang đó không lặp lại bất cứ điều gì trước khi gọi start_session().

Ví dụ về lỗi không thể đoán trước:

 <?php //a white-space before <?php also send for output and arise error
session_start();
session_regenerate_id();

//your page content

Một ví dụ nữa:

<?php
includes 'functions.php';
?> <!-- This new line will also arise error -->
<?php
session_start();
session_regenerate_id();

//your page content

Kết luận: Không xuất bất kỳ ký tự nào trước khi gọi session_start()hoặc các header()chức năng thậm chí không phải là khoảng trắng hoặc dòng mới

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.