2012-12-14 37 views
0

我有一個腳本來處理髮送電子郵件。可能會有數以千計的電子郵件發送。我想向用戶顯示一個頁面,上面寫着「您的郵件正在發送」的內容,但我不想讓該頁面實際發送郵件,因爲我不希望用戶看到一個空白頁面,直到腳本完成,我也不希望用戶不得不等待腳本完成。如何從PHP執行PHP腳本而不將用戶保留在頁面上?

我想通過一個ID列表到另一個PHP頁面(讓我們稱之爲run.php),並讓它執行,而無需用戶實際訪問它。所以我會將這些ID傳遞給開始執行的頁面,但是隨後加載當前頁面,顯示消息「您的消息正在發送」。

<?php 
/* SESSION DATA HERE */ 
executeMailSend($ids); 
?> 
<html> 
<head> 
.... 
</head> 
<body> 
Your messages are being sent. 
</body> 
</html> 

我想我可以使用ajax這樣的東西,但我寧願不要讓這依賴於客戶端編碼。

另外,如果可能的話,我需要讓腳本在後臺運行,從會話中啓動會話數據,我寧願不必將這些數據作爲單獨的變量傳遞。

此外,我不想使用任何像exec()或system()。

任何想法?

+0

是什麼您尋找在PHP這限制了選項來創建一個異步任務的方式。 PHP腳本執行的生命週期通常是HTTP事務的生命週期。一旦請求被滿足並且完全響應(如你所期待的),該進程就會被終止。你唯一的選擇是在HTTP請求仍然打開的情況下完成任務 - 保持瀏覽器停止工作,並要求他們不要關閉會話,分離進程並允許它繼續運行,或者使用其他方法來調用進程用戶請求。 – JSON

回答

0

利用AJAX的力量獲取更多信息結帳本教程你可以使你的腳本添加電子郵件至「電子郵件查詢」,並安排一個cron作業來發送電子郵件。我不認爲有其他方式異步調用PHP腳本。

也許這會爲你指明正確的方向:http://blog.markturansky.com/archives/205

+0

我無法使用cron作業。這有很長的理由,但我希望我能。 – tvirelli

+0

恐怕你唯一的選擇是ajax。或者製作一個外部終端程序,用於掃描某些文件/數據庫以發送電子郵件,並調用您的PHP腳本以實際發送它們。因爲PHP不支持異步調用,所以我認爲沒有其他方法可行。 – 2012-12-14 03:43:29

+0

另一件事讓我想起,它可能是最簡單的解決方案,雖然不是最優雅的一個:http://php.net/manual/en/misc.configuration.php#ini.ignore-user-abort 缺點是您的用戶瀏覽器將顯示*加載*指示符,直到發送電子郵件。 – 2012-12-14 14:20:04

0

,如果你有機會獲得一臺Linux機器;你可以使用一些叫做Cronjobs的東西。

您可以使用它自己的數據庫表創建一個單獨的腳本,它用作參考。

按設定的時間間隔,它通過PHP的Linux CLI運行PHP並執行腳本,沒有用戶需要在頁面上。數據庫需要正確配置。

唯一的問題是有cronjobs,所有輸出通過電子郵件發送到管理電子郵件(/etc/aliases

實例上的cronjob輸入:

nano /etc/crontab 

* * * * * root /usr/bin/php /var/www/cron.php 

,並在你的cron.php你將有一個腳本設置對於特定的功能,在這種情況下,電子郵件用戶。

http://www.thegeekstuff.com/2011/07/php-cron-job/

+0

我明白這是最好的選擇,對我來說不幸的是,這不是一種選擇。我不能在這個項目中使用cronjobs。如前所述,我想,但這不會發生在這個項目上。 – tvirelli

1

一個cron作業是一個選項。您合作通過在數據庫中實現一個隊列來完成它,你只需要添加要發送的郵件的條目,並且cron作業處理這些條目。但可能在下一條道路前閱讀:http://www.engineyard.com/blog/2011/5-subtle-ways-youre-using-mysql-as-a-queue-and-why-itll-bite-you/

如果您使用cron作業,您將在某處執行隊列(平面文件... blech,MySQL和其他數據庫等)。)

爲什麼不使用實際用於排隊的內容?例如,你可以使用亞馬遜(http://aws.amazon.com/sqs/)。但是無論您使用哪種軟件/提供程序,這聽起來像是在正確的工作排隊時最好。您希望用戶轉到一個頁面,該頁面會將一些工作項添加到您的隊列中(在這種情況下,這些電子郵件地址和消息可能取決於您正在執行的操作)。然後隊列軟件應該有一些處理這些作業的手段(即實際發送電子郵件)。

你說你不想傳遞變量,但是你可能必須發送你需要的任何數據給你的隊列。您可能會將額外數據存儲到數據庫,只需考慮鎖定和性能。

0

我想我將不得不堅持我目前的選擇,這是我以前使用的腳本。我希望找到一個更好的選擇,但這裏是我將要使用的代碼:

function backgroundPost($url){ 
    $parts=parse_url($url); 
    $fp = fsockopen($parts['host'], isset($parts['port'])?$parts['port']:80, $errno, $errstr, 30); 

    if (!$fp) { 
     return false; 
    } else { 
     $out = "POST ".$parts['path']." HTTP/1.1\r\n"; 
     $out.= "Host: ".$parts['host']."\r\n"; 
     $out.= "Content-Type: application/x-www-form-urlencoded\r\n"; 
     $out.= "Content-Length: ".strlen($parts['query'])."\r\n"; 
     $out.= "Connection: Close\r\n\r\n"; 
     if (isset($parts['query'])) $out.= $parts['query']; 

     fwrite($fp, $out); 
     fclose($fp); 
     return true; 
    } 
} 

backgroundPost($siteURL.'/run.php?ids='.urlencode($ids).'&sessiondata='.urlencode($sessiondata)); 

有沒有人看到使用此問題?安全性,糟糕的代碼等?