2013-02-13 37 views
22

Có, câu hỏi này đã được hỏi trước, tuy nhiên, câu trả lời đã không phù hợp. Lấy ví dụ Why I have to call 'exit' after redirection through header('Location..') in PHP?. Mỗi câu trả lời (bao gồm cả câu trả lời được chấp nhận) đều có, ngoại trừ câu trả lời cuối cùng nhận được số phiếu không nói là "có thể". Tôi bắt đầu nghĩ rằng câu trả lời đúng là "có thể". Để làm cho nó một câu hỏi "có" hoặc "không" đơn giản, sẽ làm điều này() được thực hiện cho kịch bản sau đây? Cảm ơnTập lệnh PHP có được thực thi sau khi chuyển hướng tiêu đề không?

header('Location: http://somewhereElse.com'); 
//die(); 
sleep(1000); 
doThis(); 

EDIT Xin cảm ơn, tất cả. Với cấu hình PHP/Linux/Apache của tôi, syslog thứ hai() thực hiện, do đó, câu trả lời là "có, tất cả luồng tập lệnh của tiêu đề sẽ được thực thi". Tôi sẽ giả định (và hy vọng tôi là chính xác) nó là như nhau với tất cả các cấu hình PHP/Linux/Apache!

<?php 
    header('Location: http://google.com'); 
    syslog(LOG_INFO,'first'); 
    sleep(5); 
    syslog(LOG_INFO,'Second'); 
?> 
+3

Bạn đã thử chưa? Thời gian ngủ trong ví dụ của bạn sẽ vượt quá 'max_execution_time'. Nếu không, có. – mario

+1

Có, mặc dù bạn không cần lệnh gọi 'sleep()'. 'header()' không ngừng thực hiện, chỉ đặt tiêu đề phản hồi – Phil

+0

Không, chưa thử. Xấu hổ với tôi! Đọc bài viết cuối cùng trên chủ đề SO được tham chiếu ban đầu của tôi cũng như các câu trả lời cho http://stackoverflow.com/questions/7246649/will-all-code-after-redirect-header-in-php-always-get-executed, nó xuất hiện rằng Apache sẽ đóng kết nối và tập lệnh PHP sẽ ngừng thực thi. – user1032531

Trả lời

18

Có, tập lệnh tiếp tục xử lý sau khi gọi tới header('Location: http://google.com') nếu bạn không chấm dứt rõ ràng! Tôi vừa thử nó ở địa phương. Tôi thêm test.php đến một trang web trong apache với những nội dung:

<?php 

header('Location: http://google.com'); 
error_log("WE MADE IT HERE SOMEHOW"); 

?> 

Và kiểm tra của tôi/var/log/apache2/error_log cho cụm từ này:

[Tue Feb 12 23:39:23 2013] [error] [client 127.0.0.1] WE MADE IT HERE SOMEHOW 

Có lẽ đáng ngạc nhiên, nhưng có, nó tiếp tục thực thi nếu bạn không ngừng thực hiện.

+0

Tôi cảm thấy lame vì không thử nghiệm! Tuyệt vời cho bạn Cody! Về phương pháp khoa học! Tôi cũng sẽ kiểm tra và đăng các phát hiện của tôi. – user1032531

+0

Cảm ơn Cody. Tôi đã thử nghiệm và đồng ý với kết quả của bạn. Lý do tôi hỏi trước khi thử nghiệm là tôi đã không chắc chắn nếu nó đã được xác định cấu hình. Tôi sẽ trong tương lai giả định rằng nó sẽ luôn luôn được thực hiện bất kể hệ điều hành hoặc máy chủ web. – user1032531

0

Có, nó sẽ được thực hiện trong một khoảng thời gian ngắn.

Khi tiêu đề chuyển hướng được gửi tới trình duyệt, trình duyệt sẽ đóng kết nối hiện tại và mở kết nối mới cho URL chuyển hướng. Cho đến khi kết nối ban đầu đó bị đóng và Apache tắt tập lệnh , mã của bạn sẽ tiếp tục thực hiện như trước.

Về lý thuyết, nếu có một kết nối đủ nhanh giữa client/server, và không có đệm bất cứ nơi nào trong các đường ống, ban hành tiêu đề sẽ gây ra các kịch bản để được chấm dứt ngay lập tức . Trong thực tế, nó có thể là bất cứ nơi nào giữa "bây giờ" và "không bao giờ" để tắt máy để bắt đầu.

Read more

+0

Vì vậy, câu trả lời là không, cho 1000 giây (hoặc bất cứ điều gì) chậm trễ? – user1032531

+0

tùy thuộc vào kết nối internet của bạn. – Techie

+0

Tôi nghĩ rằng nó phụ thuộc vào khách hàng là tốt. Ví dụ: một số khách hàng yêu cầu trang và không tôn trọng tiêu đề. –

5

Hãy để tôi giải thích thêm. chúng ta hãy có một ví dụ sử dụng phiên.

$_SESSION["username"] = 'some username'; 
header("Location: another-file.php"); 
$_SESSION["username"] = 'replace username';

Kết quả $_SESSION["username"] sẽ replace username

Bạn có thể xuất tiêu đề nhiều hơn chỉ tiêu đề Location với tiêu đề, hầu hết trong số đó bạn không muốn dừng thực thi mã của bạn. Nếu bạn muốn ngừng thực thi mã, bạn cần gọi số exit một cách rõ ràng.

Lệnh header không làm gián đoạn luồng mã của bạn. Ngay cả khi điều đó gặp phải, trang của bạn vẫn được trình duyệt tải xuống, ngay cả khi trang đó không hiển thị. Hãy xem xét 404 pages, mà (mặc dù là lỗi) vẫn được xử lý bởi trình duyệt (mặc dù chúng được hiển thị trong khi chuyển hướng không được).

0

vâng có, tiêu đề giống như bất kỳ phần nào khác của tập lệnh php, nó sẽ được gửi sau khi hoàn thành tập lệnh, tuy nhiên, mẹo là: nếu chúng tôi muốn chuyển hướng đến URL mới: thì tại sao tiếp tục thực thi tập lệnh sau tiêu đề ("vị trí: url"); ?>

<?php 
header('Location: test.php'); 
header('Location: test.php'); 
header('Location: test.php'); 
header('Location: test.php'); 
header('Location: test.php'); 
header('Location: test.php'); 
header('Location: test.php'); 

$var = 'google.com'; 
header("Location: http://$var"); 

?> 
3

Chạy mã:

//http://www.php.net/manual/en/function.header.php 
header('Location: http://google.com'); 
flush(); 
sleep(3); 

$a=fopen('test.txt', 'w'); 
fwrite($a,headers_sent()); 
fclose($a); 

Máy chủ dừng lại và viết các tập tin trước khi khách hàng chuyển hướng tôi. Điều này là bởi vì, ngay cả sau khi flush() ing bộ đệm, chuyển hướng không được xử lý cho đến khi tập lệnh ngừng thực hiện (tức là, tập lệnh chấm dứt). Tệp test.txt có '1' trong mọi trường hợp, có nghĩa là các tiêu đề đã được gửi, không được trình duyệt xử lý cho đến khi kết nối bị chấm dứt.

  • trong mọi trường hợp, có nghĩa là trên máy phát triển win32, máy phát triển linux và môi trường sản xuất Linux.
7

Mọi người dường như nhận được điều này thực sự bối rối và về lý do tại sao tập lệnh được thực thi. Khi bạn gửi tiêu đề chuyển hướng, trình duyệt sẽ chuyển hướng người dùng đến trang mới ngay lập tức nhưng máy chủ của bạn sẽ tiếp tục xử lý mã ngay cả khi không có ai nhận nó ở cuối, điều này không có nghĩa là tập lệnh bị chấm dứt. Trừ khi bạn cấu hình Apache để dừng kịch bản khi nó nhận ra không có ai ở đầu kia.

Khi tập lệnh PHP chạy bình thường trạng thái NORMAL, đang hoạt động. Nếu máy khách từ xa ngắt kết nối cờ trạng thái ABORTED được bật. Một khách hàng từ xa ngắt kết nối thường là do người dùng nhấn nút STOP của mình.

Bạn có thể quyết định xem bạn có muốn một khách hàng ngắt kết nối gây ra tập lệnh của bạn bị hủy bỏ hay không. Đôi khi, bạn luôn có thể chạy các tập lệnh để hoàn thành ngay cả khi không có trình duyệt từ xa nào nhận được đầu ra. Tuy nhiên, hành vi mặc định cho tập lệnh của bạn là bị hủy khi máy khách từ xa ngắt kết nối. Hành vi này có thể được đặt thông qua chỉ thị php.ini ignore_user_abort cũng như qua tương ứng php_value ignore_user_abort Apache httpd.conf chỉ thị hoặc với chức năng ignore_user_abort().

Cách đúng đắn về chuyển hướng người dùng không có hành động hơn nữa là:

header("Location: blah.php"); 
exit(); 
0
header("Location: http://example.com/newURL.php"); 
die; 

Có kịch bản tiếp tục sau khi chuyển hướng tiêu đề, vì vậy hãy chắc chắn để gọi die; hoặc exit; bất cứ lúc nào bạn bạn chuyển hướng để ngừng thực hiện. Không cần phải đặt kịch bản để ngủ :).

How to make a redirect in PHP?

1

ví dụ đầu tiên này cho thấy một số mã được thực thi sau khi tiêu đề vị trí chuyển hướng, nhưng đó không phải tất cả các mã được thiết thực. Khi trình duyệt bắt đầu phản hồi tiêu đề chuyển hướng, trình duyệt sẽ chấm dứt kết nối trên trang hiện tại, điều này sẽ khiến cho PHP chấm dứt thực thi mã của nó. Điều này cho thấy làm thế nào để không làm việc.

session_start(); 
$_SESSION["some_value"] = 'original value'; 
header("Location: /index.php/test2"); 

$start_time = microtime(true); 

for($i = 0; $i <= 100000; $i ++) 
{ 
    password_hash($i); // slow it down 
    $_SESSION["some_value"] = $i; 
    $_SESSION['time'] = microtime(true) - $start_time; 
} 

$_SESSION['some_value'] = 'finished!'; 

// Result: 
// some_value = 174 

Trong ví dụ này tôi đã thêm ignore_user_abort() để hiển thị như thế nào để thực hiện tất cả các mã:

ignore_user_abort(TRUE); 
session_start(); 
$_SESSION["some_value"] = 'original value'; 
header("Location: /index.php/test2"); 

$start_time = microtime(true); 

for($i = 0; $i <= 100000; $i ++) 
{ 
    password_hash($i); // slow it down 
    $_SESSION["some_value"] = $i; 
    $_SESSION['time'] = microtime(true) - $start_time; 
} 

$_SESSION['some_value'] = 'finished!'; 

// Result: 
// some_value = finished! 

Và đây là cách bạn thường sẽ thực hiện một chuyển hướng, bằng cách giết chết các tập lệnh ngay lập tức sau khi chuyển hướng :

session_start(); 
$_SESSION["some_value"] = 'original value'; 
header("Location: /index.php/test2"); 
die(); 

$start_time = microtime(true); 

for($i = 0; $i <= 100000; $i ++) 
{ 
    password_hash($i); // slow it down 
    $_SESSION["some_value"] = $i; 
    $_SESSION['time'] = microtime(true) - $start_time; 
} 

$_SESSION['some_value'] = 'finished!'; 

// Result: 
// some_value = original value 

Trong ngắn hạn, hãy sử dụng die(), exit() hoặc ignore_user_abort (TRUE);

+0

Ở cuối nhận xét của bạn, không phải bạn có nghĩa là ignore_user_abort (FALSE)? – MarcoZen

-1

SỬ DỤNG SCENARIO: Chuyển hướng người dùng đến cổng bị khóa rồi bắt đầu đồng hồ đếm ngược để ghi chúng ra khỏi danh sách chặn sau x phút.

Các vấn đề liên quan