无论如何我可以在CodeIgniter中实现类似新线程的东西吗?

时间:2014-11-01 01:42:32

标签: php codeigniter

所以CodeIgniter基本上有一种方法可以进行异步操作吗?

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

CodeIgniter或PHP中是否有一种方法可以启动发送电子邮件(或其他任何操作),并继续执行脚本而不等待它结束?

我唯一能想到的就是以某种方式制作它可能会让某些cron独立于该脚本执行该操作。但是我可以在脚本中做些什么吗?

3 个答案:

答案 0 :(得分:1)

您还可以将条目添加到消息队列中,例如rabbit mq或zero mq,这样您就可以稍后异步处理该消息。看看react-php也可能有所帮助。

答案 1 :(得分: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'
   });
});

答案 2 :(得分:1)

这就是我在CI中所做的,

创建index.php的副本,将其移到webroot上方,即。在浏览器中无法访问的位置。在此索引文件中 - 其中显示DEFAULT CONTROLLER添加此行

$routing['controller'] = 'cli';

这将锁定或监禁index.php文件以仅使用控制器中的cli.php文件,这样Web上的用户就无法启动此控制器方法。出于安全原因,这很重要。还有一些其他好处,它为您的后台脚本提供了一个独立的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变量和事物存在一些差异。但它是&#34;适当的&#34;这样做的方法。

这已经从我的设置中删除了,所以不确定它是否会正常工作,但它应该让你开始。 RabbitMq对于这个有点矫枉过正,当你需要的只是一个后台进程。顺便说一下,这只是我的RabbitMq设置的一小部分。如果你需要一个完整的排队系统,兔子真棒,但是它的安装和学习曲线与客户使用等等。

请注意,您需要能够在php中使用runexec命令。也永远不要将用户输入放在shell命令的参数中,这是将索引文件移出Web可访问位置的主要原因。仅使用经过适当验证的输入调用此方法。我确实有escapeshellarg来清理输入,但我不会仅仅依赖它。

顺便说一下,在Windows上运行适当的后台进程需要几天时间。

正如其他人所说,使用Ajax可以更轻松地完成它,但是你有使用httpd服务器的开销。这与使用cron运行它类似,但没有cron。如果您熟悉,那么命令行调用看起来应该与cron调用非常相似,除非您使用curl作为yuck

干杯!