所以CodeIgniter基本上有一种方法可以进行异步操作吗?
例如,注册后我想发送电子邮件。这往往需要一两秒钟,用户必须等待相当长的时间。
CodeIgniter或PHP中是否有一种方法可以启动发送电子邮件(或其他任何操作),并继续执行脚本而不等待它结束?
我唯一能想到的就是以某种方式制作它可能会让某些cron独立于该脚本执行该操作。但是我可以在脚本中做些什么吗?
答案 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中使用run
或exec
命令。也永远不要将用户输入放在shell命令的参数中,这是将索引文件移出Web可访问位置的主要原因。仅使用经过适当验证的输入调用此方法。我确实有escapeshellarg
来清理输入,但我不会仅仅依赖它。
顺便说一下,在Windows上运行适当的后台进程需要几天时间。
正如其他人所说,使用Ajax可以更轻松地完成它,但是你有使用httpd服务器的开销。这与使用cron运行它类似,但没有cron。如果您熟悉,那么命令行调用看起来应该与cron调用非常相似,除非您使用curl作为yuck
。
干杯!