繁体   English   中英

php 停止包含文件,同时继续实际文件中的循环?

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

我有 2 included.php文件让我们说一个index.php

index.php

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

包括。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中的循环,当测试仪 class 被激怒时执行第一部分,然后等待我说的一分钟?

可能的? 还是我需要别的东西?

您无法使用 PHP 执行此操作。 它不是多线程语言。 您可以通过并行执行 PHP 的另一个副本来模糊地模拟它,但这不是真正的线程 - 它是两个完全独立的进程,恰好执行相同的脚本。

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

这个问题非常笼统,但我认为这不是使用 php 的正确方法......通常 php 会尝试尽快执行操作,例如渲染网页。 如果你想添加时间和动态的东西,那么每次你想执行脚本时都必须向服务器发送单独的请求。

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

您可以编写一个新脚本 testerStart.php,您可以通过 url 访问它。 这样,您实际上会调用服务器上的另一个脚本,该脚本将与您的初始脚本独立运行。

所以 index.php 看起来像:

<?php
  while(true)
  {
     $i++;
     sleep(3);
     // call testerStart.php asynch
  }
?>

testerStart.php 看起来像:

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

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

此外,如果您有 PHPClasses 帐户,我发现的链接可能与您相关: PHP PCNTL 包装器 class

我不确定,但你可以尝试类似

<?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');在单独的进程中启动一个脚本并获得一个可读的 pipe (这样我们就可以读取该进程的输出)。 当 object 在那个单独的进程中成功创建时,我们序列化和 output 结果。 回到主脚本,每次迭代我们检查已经打开的实例,如果其中一些返回一些东西——我们将这些内容视为序列化的 object,将其反序列化,然后随心所欲地处理它; 然后在完成我们想要的操作后,我们关闭该进程并将其从打开的实例列表中删除。 实际上,如果您的代码中的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 的网络应用程序中需要它时,您需要查看其他解决方案,因为分叉您的进程将不起作用。

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

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

我进行了更多研究并运用了自己的思想,最终我自己找到了一种方法:

index.php

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

包括。php

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

这就像一个魅力

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM