php背景執行
有些功能需要長時間處理或是不方便一次處理過多數量的通常就會使用背景處理,有幾種方式不過基本上需要伺服器設定能配合。
以自己的情況來說,最常使用背景處理的就是email的寄送,有些主機沒有設定批次寄信的處理或間隔時間,避免短時間內寄出過多信件而加入間隔時間的處理。
第1種方式是使用curl觸發
伺服器設定無法配合的話可能能考慮使用這種方式,利用不等待網頁回應的curl觸發長時間執行的檔案來進行,比較大的問題是在新版(php7)環境中可能是內建安全機制的關係,執行的時間似乎有上限,使用時請務必測試看看在自己的環境上會不會中斷,這邊測試的情況無論怎麼設定最多只能跑到4小時左右,使用這種方式的話需要設計能從中斷點手動重新觸發處理的機制。
//不等待回應的curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, '網址');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
//curl_setopt($ch, CURLOPT_POST,true);
curl_setopt($ch, CURLOPT_POSTREDIR, 3);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
'參數名' => '參數值'
)));
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1);
curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
$r = curl_exec($ch);
curl_close($ch);
處理頁上的設定
ignore_user_abort(true);//瀏覽器關閉後繼續執行
set_time_limit(0);//讓程式執行到結束為止
在頁尾重新呼叫自己
$retime = time() + 900;//重新啟動時間 15分鐘
$resendflag = false;
//從資料庫讀出的信件迴圈中加入時間判斷
if(time() > $retime){
//超時 設定跳出並觸發
$resendflag = true;
break;
}
if($resendflag==true){
//重新啟動寄送
}else{
//發信完成動作
}
第2種則是呼叫Linux指令觸發排程功能,產生sh檔案後使用指令執行,需要注意php是否有權限呼叫,因為安全性的關係基本上預設是關閉的。
$file = "edm_send.sh";
//檔案名稱 參數1 參數2
$content = "php edm_send.php ".$id." ".$subscriber;
$fbody = fopen($file,"w");
fwrite($fbody,$content);
fclose($fbody);
unset($content);
//00:00 2011-03-24 批次時間格式
$settime = date("H:i Y-m-d",mktime(date("H"), date("i")+2, 0, date("m"), date("d"), date("Y")));
exec("at -f ".$file." ".$settime);
其中排程觸發的參數可以用argv取得,如果沒有的話檢查php的register_argc_argv設定
//用argv取得參數
$argv[0]="test.php";
$id = $argv[1];
$subscriber = $argv[2];
第3種則是使用主機設定 crontab 排程定期觸發檔案,只要注意執行的檔案不會重複處理,還有能夠從每次結束的地方繼續處理就好。