所以基本上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