Pytanie w sprawie php, redirect, header – Jak wywołać przekierowanie przed zakończeniem skryptu php?

9

Chcę uruchomić skrypt php, który wyśle ​​kilka e-maili (biuletynów), ale ponieważ może to chwilę potrwać, aby uruchomić, chcę, aby użytkownik został natychmiast przekierowany na stronę z komunikatem „Twoje biuletyny są w kolejce, aby być Wysłany."
Jak dotąd przekierowania nagłówka działają, ale nie powodują przekierowania, dopóki wszystkie wiadomości e-mail nie zostaną wysłane. Czy mogę zamknąć połączenie po wysłaniu przekierowania, aby przeglądarka natychmiast zareagowała na przekierowanie? Próbowałem takich rzeczy

<code>
ob_start();
ignore_user_abort(true);
header( "refresh:1;url=waitforit.php?msg=Newsletters queued up, will send soon.");
header("Connection: close");
header("Content-Length: " . mb_strlen($resp));
echo $resp;
//@ob_end_clean();
ob_end_flush();
flush();
</code>

w różnych permutacjach i kombinacjach, ale bezskutecznie. Podejrzewam, że nie można tego zrobić w prosty sposób, ale zanim zacznę bawić się zadaniami cron lub niestandardowymi demonami, pomyślałem, że zajrzę do tego podejścia. Dzięki

np. jak blokada sugeruje poniżej, ale nie ma szczęścia

<code>ob_start();
ignore_user_abort(true);
header( "refresh:1;url=mailing_done.php?msg=Newsletters queued for sending.");
header("Connection: close");
header("Content-Length: 0" );
//echo $resp;
ob_end_flush();
flush(); </code>

Twoja odpowiedź

7   odpowiedzi
1

zaakceptowana odpowiedź nie działała dla mnie, ale tak się stało. Pamiętaj, że ignore_user_abort () musi być włączony w php.ini

<code>ignore_user_abort(true);
    session_write_close(); // optional, this will close the session.
    header("Location: $url");
    header("Content-Length: 0");
    ob_end_flush();
    flush();
    //do_function_that_takes_five_mins();
</code>

http://waynepan.com/2007/10/11/how-to-use-ignore_user_abort-to-do-process-out-of-band/

1

Aby to działało na IIS7, musisz używać isapi zresponseBufferLimit="0" w web.config i output_buffering = Off w php.ini, wtedy coś takiego powinno działać ...

<code>  session_write_close();
  header( ,"Location: ".$sURL ) ;
    // try to allow continued processing
  if(ob_get_length())
    ob_end_clean();
  header("Connection: close");
  ignore_user_abort(); // optional
  ob_start();
  header("Content-Length: 0");
  ob_end_flush(); // Strange behaviour, will not work
  flush(); // Unless both are called !
</code>
3

Oto właściwy sposób, aby to zrobić ... code by Sonia Desbiens, alias: fataqui 07/01/2005

<code><?php

set_time_limit ( 0 );

/* start the forced redirect */

header ( 'Connection: close' );

ob_start ();

/* close out the server process, release to the client */

header ( 'Content-Length: 0' );

header ( 'Location: /page_to_redirect_to.php' );

ob_end_flush ();

flush ();

/* end the forced redirect and continue with this script process */

ignore_user_abort ( true );

/* the rest of your script here */

/*
 * this example will redirect the user to '/page_to_redirect_to.php'
 * then this script will continue by sleeping for '10' seconds, then
 * this script will write a file, and then this script will exit...
*/

sleep ( 10 );

file_put_contents ( './out.txt', '' );

exit ();

?>
</code>
1

Spróbuj ustawićContent-Length do 0

Spróbuj teżConnection: close, widziećphp.net/manual/en/features.connection-handling.php#104541 blockhead
Po prostu spróbowałem, ale nie miałem szczęścia. lost baby
0

Zasadniczo szukasz asynchronicznego wykonywania zadania. Chciałbym, aby skrypt php utworzył inny wątek (lub proces), który wysyła asynchronicznie wiadomości e-mail. W ten sposób wątek, w którym działa żądanie, nie jest związany z przetwarzaniem wiadomości e-mail. Wątek przetwarzający żądanie i zwracający wynik może działać całkowicie niezależnie od wątku, który wysyła e-maile.

Ten wątek wydaje się dotykać tego podejścia, być może będzie bardziej pomocny w odniesieniu do szczegółów implementacji:Uruchom zadanie PHP asynchronicznie

6

Spróbowałbym tego:

<code><?php
header("Location: waitforit.php?msg=Newsletters queued up, will send soon.");
header("Content-Length: 0");
header("Connection: close");
flush();
//Do work here
?>
</code>
14

Jeśli chcesz uruchamiać skrypt w sposób ciągły i nadal chcesz wyświetlać dane wyjściowe, dlaczego nie użyjesz żądania ajax na serwerze, który może kolejkować wiadomości e-mail i nadal pozwalać użytkownikowi kontynuować przeglądanie tej strony.

Jeśli nie chcesz tego używać; zamiast tego możesz użyć, skrypt uruchamia tło, nawet jeśli użytkownik zostanie przekierowany doshow_usermessage.php strona

<code><?PHP
    //Redirect to another file that shows that mail queued
    header("Location: show_usermessage.php");

    //Erase the output buffer
    ob_end_clean();

    //Tell the browser that the connection's closed
    header("Connection: close");

    //Ignore the user's abort (which we caused with the redirect).
    ignore_user_abort(true);
    //Extend time limit to 30 minutes
    set_time_limit(1800);
    //Extend memory limit to 10MB
    ini_set("memory_limit","10M");
    //Start output buffering again
    ob_start();

    //Tell the browser we're serious... there's really
    //nothing else to receive from this page.
    header("Content-Length: 0");

    //Send the output buffer and turn output buffering off.
    ob_end_flush();
    flush();
    //Close the session.
    session_write_close();


    //Do some of your work, like the queue can be ran here,
    //.......
    //.......
?>
</code>
czy to działa dla ciebie, właśnie próbowałem i to nie zadziałało, czy brakuje mi jakiegoś zmarszczki? lost baby
ignore_user_abort () musi być włączony w php.ini. Mimo to zaakceptowana odpowiedź nie działała dla mnie. Proszę zobaczyć moją odpowiedź. Doug Cassidy
ciekawe, spróbuję tego. Dzięki. lost baby
Nie pracuję dla mnie. Wkleiłem twój kod, z wyjątkiem tego, że przekierowałem z powrotem do bieżącego adresu URL. $ R = 1. Przekierowuje, ale nigdy nie wykonuje pracy po. Doug Cassidy

Powiązane pytania