2014-11-01 59 views
0

所以基本上CodeIgniter中有一种方法可以实现异步操作?无论如何,我可以在CodeIgniter中实现类似于新线程的功能吗?

例如,注册后我想发送电子邮件。这往往需要一两秒钟,用户需要等待大量的时间。

那么CodeIgniter或PHP有什么方法来启动发送电子邮件(或其他任何操作),并继续执行脚本而不必等待它结束?

我能想到的唯一方法就是让某个cron执行独立于该脚本的行为。但是脚本中有什么我能做的吗?

+0

调用发送电子邮件作为异步AJAX请求的控制器操作可能是最好的解决方案。这将是浏览器中的非阻塞呼叫,这将允许用户做其他事情。 – 2014-11-01 01:49:11

+0

如果我发起ajax请求,并且用户在获得答复之前重新加载页面,会发生什么情况?甚至有可能,或者在页面可以重新加载之前完成任何AJAX请求? – galdikas 2014-11-01 01:58:11

+0

这很大程度上取决于你是否在Windows或Linux上运行,这两者都有可能。 – ArtisticPhoenix 2014-11-01 02:01:03

回答

1

您还可以将一个条目添加到像rabbit mq或zero mq这样的消息队列中,以便稍后异步处理该消息。看一下react-php也会有帮助。

1

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' 
    }); 
}); 
1

这是我在做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设置的一小部分。兔子是真棒,如果你需要一个全面的排队系统,但有安装它和学习曲线与什么客户端使用等。

请注意您需要能够使用runexec命令在PHP中。也不要将用户输入放在shell命令的参数中,这是将索引文件移出web访问位置的主要原因。只能使用正确验证的输入来调用它。我确实有escapeshellarg来清理输入,但我不会仅仅依赖于此。

顺便说一下,这是值得几天的研究在Windows上运行适当的后台进程。

正如其他人提到的那样,使用Ajax可以更轻松地完成工作,但是您有使用httpd服务器的开销。这与使用cron运行它相似,但没有cron。如果您熟悉命令行调用应该与cron调用非常相似,除非您使用卷曲为yuck

干杯!

相关问题