所以基本上CodeIgniter中有一種方法可以實現異步操作?無論如何,我可以在CodeIgniter中實現類似於新線程的功能嗎?
例如,註冊後我想發送電子郵件。這往往需要一兩秒鐘,用戶需要等待大量的時間。
那麼CodeIgniter或PHP有什麼方法來啓動發送電子郵件(或其他任何操作),並繼續執行腳本而不必等待它結束?
我能想到的唯一方法就是讓某個cron執行獨立於該腳本的行爲。但是腳本中有什麼我能做的嗎?
所以基本上CodeIgniter中有一種方法可以實現異步操作?無論如何,我可以在CodeIgniter中實現類似於新線程的功能嗎?
例如,註冊後我想發送電子郵件。這往往需要一兩秒鐘,用戶需要等待大量的時間。
那麼CodeIgniter或PHP有什麼方法來啓動發送電子郵件(或其他任何操作),並繼續執行腳本而不必等待它結束?
我能想到的唯一方法就是讓某個cron執行獨立於該腳本的行爲。但是腳本中有什麼我能做的嗎?
您還可以將一個條目添加到像rabbit mq或zero mq這樣的消息隊列中,以便稍後異步處理該消息。看一下react-php也會有幫助。
AJAX請求?
您可以異步發送請求到您的服務器,並讓它們被任何你想要的東西觸發。一旦該功能執行並向服務器發出請求,無論用戶是否離開該頁面,該過程都將在服務器上繼續。
例如:
$('#submit-btn').on("click", function() {
function signUp(){
var email = $('#subscription').val();
var op1 = $('#option1').val();
var op2 = $('#option2').val();
var formData = new FormData();
formData.append('email', email);
formData.append('option_1', op1);
formData.append('option_2', op2);
$.ajax({
url: '/subscribe',
data: formData,
processData: false,
contentType: false,
type: 'POST'
});
});
這是我在做CI,
創建index.php文件的副本,將它的根目錄之上,即。它在瀏覽器中無法訪問。在這個索引文件 - 它說:DEFAULT CONTROLLER
加入這一行
$routing['controller'] = 'cli';
這將鎖定或坐牢是index.php文件只使用cli.php
文件中的控制器,用戶在網絡上這樣傾斜啓動該控制器的方法。這對於安全原因很重要。還有其他一些好處,它爲您的後臺腳本提供了獨立的CI環境。例如,您可以設置單獨defined('ENVIRONMENT')
您的網站,等等。
在cli.php
添加這樣的事情
/**
*
* <pre>
* <b>Windows</b>
* php -f "{path to index}/index.php" "[arg1]/[arg2]"
* <b>Linux</b>
* /usr/bin/php -f "{path to index}/index.php" "[arg1]/[arg2]"
*/
public function index(){
echo __METHOD__ . "/n";
print_r(func_get_args());
}
的意見是在命令行調用中使用。或者你可以使用我的BGPROCESS類
創建該類
class BgProcess{
/**
*
* @param string $arg0, $arg1 ...
* $arg0 is location of php file to run
* $arg1 ..is additional params to send to script
*/
public function __construct($arg0){
if(stripos(php_uname('s'), 'win') > -1){
$_osWin = true;
}else{
$_osWin = false;
}
$args = func_get_args();
$file = str_replace('\\', '/', array_shift($args));
$script = escapeshellarg($file).' '.escapeshellarg(implode('/', $args));
if(false !== ($phpPath = $this->_getPHPExecutableFromPath($_osWin))){
if($_osWin){
$WshShell = new \COM('WScript.Shell');
$cmd = 'cmd /C '.$phpPath.' '.$script;
$oExec = $WshShell->Run($cmd, 0, false);
}else{
//> /dev/null &
$cmd = $phpPath.' -f '.$script.' > /dev/null &';
exec($cmd);
}
}else{
die('Could not find php executable');
}
}
/**
*
* @return string|boolean
*/
protected function _getPHPExecutableFromPath($_osWin) {
$paths = explode(PATH_SEPARATOR, getenv('PATH'));
if($_osWin){
foreach ($paths as $path) {
if (strstr($path, 'php')){
$php_executable = $path . DIRECTORY_SEPARATOR . 'php.exe';
if(file_exists($php_executable) && is_file($php_executable)){
return $php_executable;
}
}
}
}else{
foreach ($paths as $path) {
$php_executable = $path . DIRECTORY_SEPARATOR . "php";
if (file_exists($php_executable) && is_file($php_executable)) {
return $php_executable;
}
}
}
return false;
}
}
這樣稱呼它
$BG = new BgProcess("{path to index }index.php, $arg1, $arg2 .. etc);
添加你的代碼,CLI的你通常會在一個控制器。如果不使用索引方法,像這樣調用它。
php -f "{path to index}/index.php" "[method]/[arg2]"
$BG = new BgProcess("{path to index }index.php, $method, $arg1 .. etc);
本質上講,當你在命令行或與BGPROCESS類它的路線就像正常的CI類調用它,也有因爲你是在命令行界面上運行$_SERVER
變量和東西一定的差異。但這是做到這一點的「正確」方式。
這是從我設置的所以不知道它會馬上工作,但它應該讓你開始。當你需要的是後臺進程時,RabbitMq有點矯枉過正。順便說一下,這是我的RabbitMq設置的一小部分。兔子是真棒,如果你需要一個全面的排隊系統,但有安裝它和學習曲線與什麼客戶端使用等。
請注意您需要能夠使用run
或exec
命令在PHP中。也不要將用戶輸入放在shell命令的參數中,這是將索引文件移出web訪問位置的主要原因。只能使用正確驗證的輸入來調用它。我確實有escapeshellarg
來清理輸入,但我不會僅僅依賴於此。
順便說一下,這是值得幾天的研究在Windows上運行適當的後臺進程。
正如其他人提到的那樣,使用Ajax可以更輕鬆地完成工作,但是您有使用httpd服務器的開銷。這與使用cron運行它相似,但沒有cron。如果您熟悉命令行調用應該與cron調用非常相似,除非您使用捲曲爲yuck
。
乾杯!
調用發送電子郵件作爲異步AJAX請求的控制器操作可能是最好的解決方案。這將是瀏覽器中的非阻塞呼叫,這將允許用戶做其他事情。 – 2014-11-01 01:49:11
如果我發起ajax請求,並且用戶在獲得答覆之前重新加載頁面,會發生什麼情況?甚至有可能,或者在頁面可以重新加載之前完成任何AJAX請求? – galdikas 2014-11-01 01:58:11
這很大程度上取決於你是否在Windows或Linux上運行,這兩者都有可能。 – ArtisticPhoenix 2014-11-01 02:01:03