PHP停止包含文件,而在实际文件中继续循环


php stop included fle while continue with the loop in actual file?

我有两个文件一个是index.php,另一个是included.php

index . php

<?php
include 'included.php';
while(true)
{
     $i++;
     sleep(3);
     $o = new tester();
}
?>

included.php

<?php
class tester{
public function __construct() {
//execute something
//wait for lets say one minute without stoping the flow of main loop.
//Rest code
}

?>

我想要的是不要停止循环在index.php当测试类被激活时,执行第一部分,然后等待我所说的一分钟?

可能吗?或者我需要别的东西吗?

在PHP中不能这样做。它不是一种多线程语言。您可以通过并行执行另一个PHP副本来模糊地模拟它,但这不是真正的线程——它是两个完全独立的进程碰巧执行相同的脚本。

不能在一个PHP实例中同时执行一个脚本的两个或多个不同部分

这个问题很普遍,但我不认为这是使用php的正确方法…通常情况下,PHP会尽可能快地执行任务,例如渲染网页。如果你想添加定时和动态的东西,你就必须在每次执行脚本时向服务器发送单独的请求。

也许CRONJOBS或AJAX更适合您尝试做的事情。

您可以编写一个新的脚本teststart .php,您可以通过url访问它。这样你就可以调用服务器上的另一个脚本,它将独立于你的初始脚本运行。

所以index。php看起来像:

<?php
  while(true)
  {
     $i++;
     sleep(3);
     // call testerStart.php asynch
  }
?>
  • 详情见http://petewarden.typepad.com/.../how-to-post-an.html
  • 在https://stackoverflow.com/.../how-do-i-make-an-asynchronous-get-request-in-php
  • 找到此文件

teststart .php如下:

<?php
  include 'included.php';
  $o = new tester();
?>

您可能想看看PHP中的一些PCNTL函数。我自己没有太多的经验,但是前一段时间偶然发现了它。无论如何,这都不是真正的线程,但可能会让你更接近你想要实现的目标。

如果你有一个PHPClasses帐户,我发现一个链接可能与你相关:一个PHP PCNTL包装类

我不确定,但你可以试试

<?php
include 'included.php';
$instances = array();
while(true)
{
    foreach ($instances as $key => $instance) {
        if ($result = stream_get_contents($instance)) {
            pclose($instance);
            unset($instances[$key]);
            $o = unserialize($result);
            // do something with the object
        }
    }
    $instances[] = popen('php /path/to/include.php', 'r');
}
?>

<!-- in include.php -->
<?php
include 'included.php';
echo serialize(new tester());
?>

或者你可以把所有的逻辑都移到"include.php",这样主脚本就根本不关心结果了,你只需要返回任何东西,这样主脚本就知道它可以关闭进程句柄了。

在这里,我们使用popen('php /path/to/include.php', 'r');在单独的进程中启动一个脚本,并获得一个可读的管道(因此我们可以读取该进程输出的内容)。当对象在单独的进程中成功创建时,我们序列化并输出结果。回到主脚本,每次迭代我们检查已经打开的实例,如果其中一些返回一些东西-我们将这些内容视为序列化对象,反序列化它,然后对它做任何我们想做的事情;然后,在完成我们想要的之后,我们关闭该进程并将其从打开的实例列表中删除。实际上,如果while(true)在你的代码中并没有真正永远运行,而是直到满足一定的条件-这将是一个好主意,将处理部分移动到单独的周期,在初始化之后…像

while($condition)
{
    $instances[] = popen('php /path/to/include.php', 'r');
}
while ( !empty($instances) ) {
    foreach ($instances as $key => $instance) {
        if ($result = stream_get_contents($instance)) {
            pclose($instance);
            unset($instances[$key]);
            $o = unserialize($result);
            // do something with the object
        }
    }
}

您确实需要更复杂的设置。

您可能确实想看看前面提到的pcntl函数,尽管这些函数只建议在使用cli时使用。当你需要在Apache上的web应用程序中使用它时,你需要考虑其他解决方案,因为fork进程将不起作用。

其他解决方案,如前面提到的popen是另一个很好的解决方案,尽管它可能使您的代码依赖于您的体系结构(unix上的路径与windows上的路径不同,您需要确定'php'是可调用的,…)

如果以上两种可能性都没有选择,我建议使用curl或fsockopen与stream_set_blocking禁用进行异步http请求。这将是相当多的工作,然而,异步调用将使后台脚本运行,你的父脚本可以简单地继续。然后在父进程的循环中,偶尔检查后台脚本是否已经完成-使用fsockopen: stream_get_contents($resource)直到feof($resource)

我做了更多的研究,用了我的头脑,最后我自己找到了一个方法,我做到了:

index . php

<?php
$cmd = "php -q nah.php";
exec($cmd);
while (true)
{
sleep(1);
echo "lalal";
}
?>

included.php

<?php
echo "yaya";
sleep(3);
?>

这句话很有魅力