2014-02-06 85 views
2

好的,請原諒我,如果這是另一個問題的重複,但搜索後我還沒有找到明確的答案。我基本上想要做的是讓我的PHP Web應用程序觸發一些事件(如電子郵件或報告生成器),可能需要幾分鐘才能完成並立即將控制權返回給頁面。我來自.NET世界,可以很容易地通過線程來完成。在長時間運行的過程中在php中創建後臺進程

因此,這裏的工作流程:

  1. 用戶點擊「生成報告」按鈕
  2. Ajax調用「../blah/generate-report」造,並立即返回
  3. 進程已啓動並運行直到完成,而用戶可以然後去他的生意
  4. 用戶可以返回到報告頁面,看到進步:「報告完成了50%」

完成此操作的最佳方法是什麼?簡單的答案很好。我不想爲我寫的代碼,只是一些指導。我看着shell_exec,但我不確定這是否是最好的方式,或者如果是,如何使用它來處理Web應用程序中的功能。 (如果這有什麼區別,我使用Yii框架)。謝謝。

-Jason

+0

PHP是單線程的。如果你有過程控制擴展,你可以產生額外的PHP進程,但它們不是線程,也就是說。或者,您可以'exec('/ usr/bin/php name_of_script.php')' – GordonM

+0

爲了糾正上面的註釋,存在pthreads擴展,它向開發者公開了線程功能。但是,即使如此,您仍然無法爲HTML服務並執行後臺任務,因爲Web服務器進程會一直掛起直到PHP進程完成,並且只有在所有線程都完成後纔會完成。你正在尋找的是實現一個作業服務器或任務場。 Gearman想到並可能會有所幫助。您可以使用Web請求填充不同進程的隊列。然後執行另一個HTTP請求來查詢作業狀態。 –

+0

另一個意見,糾正我自己的:)如果你有興趣有任何機會使用線程,你可以檢查出我將鏈接[這個例子]的存儲庫(https://github.com/krakjoe/pthreads /blob/master/examples/SimpleWebRequest.php),它顯示瞭如何執行一個異步請求,如果這樣可以解決你的問題(雖然Drew提供的答案可以用較少的麻煩來處理這個任務)。 –

回答

1

最好的(也是唯一的據我所知)的方式開始新的 線程 線程像PHP的事情是創建一個使用像嫋嫋的新PHP請求。

$ch = curl_init(); 

curl_setopt($ch, CURLOPT_URL, 'http://www.yoursite.com/background-script.php'); 
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); 
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1); 

curl_exec($ch); 
curl_close($ch); 

這將運行腳本,並立即返回頁面。當然,沒有回調,所以最好的辦法是將background-script.php的輸出放到數據庫中,然後每隔一段時間從客戶端ping數據庫,直到看到結果。

+0

[因爲使用實際的線程會不好?](https://github.com/krakjoe/pthreads) –

+0

這只是轉發原始請求,即。它不會使其異步。例如:如果background-script.php在第1分鐘內沒有回覆,則在同一會話內發送的任何異步請求都將等待後臺腳本發送其響應。那是什麼異步? –

1

據我所知,shell_exec或exec將阻止您的PHP腳本的執行,直到進程終止。 一個解決方案是在命令的最後附加一個「&」,腳本/程序將會背景。

"/usr/report.sh &" 

我已經使用類似的東西來運行PHP從外部工具,但路過的中介腳本來控制PID,實例數... 不能說如果是Windows主機下工作。

1

我們在這裏創建了一個函數,它返回瀏覽器的答案並繼續執行。我們用它發送電子郵件,而不讓用戶等待它。

public function redirectAndContinue($url) 
{ 
    ignore_user_abort(true); 
    header("Location: $url"); 
    header("Connection: close"); 
    header("Content-Length: 0"); 
    flush(); 
} 

你可以使用它像這樣

// do quick basic stuff to validate your report 

$this->redirectAndContinue($url) 

// send your email or do other slow stuff 

的問題是:它不與AJAX工作,它必須是一個正常的網頁請求(可能帶有POST)。但是,無論如何,您可以創建進度條:在數據庫或會話中保存某些內容,然後繼續調用某個URL以通過AJAX獲取進度。

0

我可以建議Gearman?您可以將作業提交給gearman服務器並請求狀態。

Gearman提供了一個分佈式應用程序框架,可用於多臺機器或進程。它允許應用程序並行完成任務,負載平衡處理和在語言之間調用函數。該框架可以用於各種應用程序。 Gearman是多線程的,已知能夠每秒執行5萬個作業。

快速教程是在這裏:http://www.sitepoint.com/introduction-gearman-multi-tasking-php/

它也很容易上手,並且所有的代碼將在PHP。

相關問題