Skoro to wysyłanie newslettera, co podejrzewałem, to najlepiej dać sobie spokój z wyświetlaniem czegokolwiek na ekranie i poporcjować dane w rekurencji oraz zapomnieć, że się odpaliło skrypt, a najlepiej uruchamiać go w nocy cronem.
Ja mam mniej więcej tak to rozwiązane:
W bazie mam przy użytkowniku newslettera pole, będące datą, kiedy ostatnio skrypt newslettera próbowałem na nim wykonać, sam skrypt puszczam codziennie, ale mogę i nawet co 10 minut, bo nie leci po całej bazie w takim wypadku.
Plik 1:
Kod
a) ignoruję zakończenie połaczenia przez usera ( odpalam crona, a nie przeglądarkę ) - ignore_user_abort(true);
b) Pobieram z bazy pakiet X userów newslettera, którzy mają datę (Y-m-d) mniejszą niż obecna,
c) w razie braku userów killuję skrypt exitem
d) wysyłam im maile,
e) update daty na dzisiejszą robię tym z paczki pobranym,
f) opcjonalnie mogę skillować ale nie jest to potrzebne.
Jak widać w takiej sytuacji nigdy tego samego dnia nie trafię dwa razy tego samego usera bo po każdym przejściu zmniejsza mi się liczba userów z datą mniejszą od obecnej, aż do momentu, gdy nie ma juz nikogo takiego. To ważne, bo bez update'u pola daty, skrypt w rekurencji wykonywałby się w nieskończoność, wciąż dla tych samych X użytkowników.
Plik 2:
die('Błąd połączenia do bazy danych MySQL.'); if($result['ile'] == 0 ) {
$handle = fopen('newsletter.log','a'); fwrite($handle, date('Y-m-d')." Koniec wysyłki newslettera.<br />"); } else {
}
Jak widać ustawiam na wszelki wypadek set time limit i user abort, łączę się z bazą i pobieram liczbę userów z datą mniejsza niż aktualna. Jeśli jest w wyniku jest zero zapisuję sobie w logu, że skrypt w tym dniu się zakończył. Jeśli jest takich userów więcej, to usypiam skrypt na ileś sekund, po czym wywołuję skrypt wysyłki porcji maili i... samego siebie oraz killuję tę instancję. W efekcie działa już kolejny "wątek" w rekurencji aż do momentu, gdy serwer nie przetworzy wszystkich rekordów. Aby to zauważyć
nie można polegać na przeglądarce, gdyż ona po pewnym czasie zamknie połączenie z serwerem i wywali, że skrypt przekroczył czas, gdyż widzi ona tylko wywołanie pierwszej instancji, która już zapewne skillowana została i działa już w tle przynajmniej 2 lub 3

Najlepiej sobie logować do pliku na serwerze poczynania skryptu, czyli albo w pliku1 lub w warunku else pliku2 coś wpisywać do loga

Ja testowałem poprzez wpisywanie do niego czasu. Działał on znacznie przekraczając owe 30s i działał wiele minut zanim zakończył działanie, gdyż ustawilem dłuższy czas w sleepie by nie zajechać serwera i dawać mu czas na wykonywanie innych działań. Ważne jest by dobrze napisać kod w plik1, bo zastosowanie rekurencji takiej jak pokazałem uruchamia co chwilę skrypt, którego serwer nie ma jak zatrzymać, gdyż spełnia wszystkie warunki nieprzekraczalności czasu wykonania wywołując się w kolejnych wątkach. Jeśli ktoś więc nie napisze go dobrze i nie przetestuje na localu to może mieć niemiłą niespodziankę na serwerze publicznym.