【问题标题】:Why would this work on one site but not another?为什么这会在一个站点上工作,而在另一个站点上却不行?
【发布时间】:2020-04-14 18:45:29
【问题描述】:

我在 php 中使用这个 js 来显示被迭代的文件名。我在 6 个不同的网站上完美运行,所有这些网站都有相同的确切代码(WordPress 插件)。但是,另一方面,在 php 完成之前,html 不会更新。这些站点中有 4 个位于同一共享主机上,因此它不工作的站点的服务器设置应该与它运行的站点相同。这就像 ob 没有启动或冲洗。

    add_action('init', array($this, 'Do_output_buffer'));

    function Do_output_buffer() {
        ob_start();
    }
   echo "<script>
      const element = document.querySelector('#filefind');
      </script>";
   @ob_flush();
   @flush();
   echo "<script>
        element.innerHTML = `<div>" . $value . "</div>`;
        </script>";
   @ob_flush();
   @flush();

谢谢!

编辑 每个请求

        $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path), RecursiveIteratorIterator::SELF_FIRST);        
        foreach ($objects as $filename => $value) {
             echo "<script>element.innerHTML = `<div>" . $filename . "</div>`;  
             </script>";
             @ob_flush();
             @flush();
        }

    ```

【问题讨论】:

  • 你能在上下文中向我们展示你是如何实际使用它的吗?您是否还有一个原因是在 ob_flush()flush() 上抑制错误消息
  • 好的,添加了一些代码来举例说明我在做什么。基本上遍历整个目录树,并希望在相同的位置显示文件名,并在它被迭代时显示。为什么要打压?好问题。我对 JS 很烂,这是一个我发现有效的代码示例,所以我保持原样。

标签: javascript wordpress output-buffering


【解决方案1】:

您尝试将echo 输出的内容发生了一些变化。

  1. 回声中的反引号可能会导致问题
  2. 结尾&lt;/script&gt; 没有得到回应。

我会把代码改成这样:

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path), RecursiveIteratorIterator::SELF_FIRST);        
foreach ($objects as $filename => $value) {
     // Enclose the echo in single quotes and use double quotes for the actual JS.
     echo '<script>element.innerHTML = "<div>' . $filename . '</div>";</script>';    
     // Remove the error suppression so you can actual see errors.
     ob_flush();
     flush();
}

我也不确定您的主插件如何与 Do_output_buffer() 函数一起使用 - 因为它是在 init 上调用的,所以它会缓冲直到它被刷新...在第一个 foreach 之后 - 然后是缓冲区 可能变得无用。如果是这种情况,您可以在每次迭代中打开缓冲区:

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path), RecursiveIteratorIterator::SELF_FIRST);        
foreach ($objects as $filename => $value) {
     // Start the buffer here.
     ob_start();
     // Enclose the echo in single quotes and use double quotes for the actual JS.
     echo '<script>element.innerHTML = "<div>' . $filename . '</div>";</script>';    
     // Remove the error suppression so you can actual see errors.
     // Flush the buffer.
     ob_flush();
     flush();
     // repeat
    }

【讨论】:

  • 好的,尝试使用 ob_start() 并关闭抑制。没有错误和同样的问题。在 html 完成之前,一个站点不会显示输出。其他站点在循环时显示文件名。这就是我不喜欢JS的原因。在这里,它起作用了。在那里,它没有,所以我永远不知道我的代码是否正确。
  • 好的,刚刚做了一个测试并在工作的非工作站点上运行 ob_get_status(true) 并发现了问题。现在我只需要弄清楚如何解决它。在工作站点上,var_dump 显示了一个缓冲区。在非工作站点上,它显示了两个缓冲区,第一个是空的,第二个有内容。我显然需要找出一种方法来跟踪我的插件正在使用哪个缓冲区。
  • 是的,如果你得到两个缓冲区,肯定有一些奇怪的东西。由于我无权访问该插件,因此在 init 挂钩中打开缓冲区似乎是个坏主意。 init 基本上每次第一次调用插件时都会运行。如果您有另一个插件或正在刷新输出缓冲区的东西,您可能会遇到冲突的缓冲区。祝你好运!
  • 实际上,我检查过了。在我运行 init 之前,有 0 个缓冲区。在初始化之后,1 个缓冲区。当代码进入我的菜单时,已经有 2 个缓冲区,而 init 是我做 ob_start 的唯一地方,而且它肯定没有做两次 init。所以,我能得出的唯一结论是其他事情开始了。我的解决方案可能不是最好的。我想一些带有 ob_get_level() 的方法会更好,但是,嗯。有用。再次感谢!
  • 很高兴你把它整理好了!
【解决方案2】:

好的,所以,问题是某个站点上的某个其他插件或主题正在创建一个额外的输出缓冲区,并且在完成后没有将其清除。当我 var_dumped ob_get_status(true) 时,我看到了这个。

  [0]=>
  array(7) {
    ["name"]=>
    string(22) "default output handler"
    ["type"]=>
    int(0)
    ["flags"]=>
    int(112)
    ["level"]=>
    int(0)
    ["chunk_size"]=>
    int(0)
    ["buffer_size"]=>
    int(16384)
    ["buffer_used"]=>
    int(0)
  }
  [1]=>
  array(7) {
    ["name"]=>
    string(22) "default output handler"
    ["type"]=>
    int(0)
    ["flags"]=>
    int(112)
    ["level"]=>
    int(1)
    ["chunk_size"]=>
    int(0)
    ["buffer_size"]=>
    int(32768)
    ["buffer_used"]=>
    int(28778)
  }
}

这意味着我发送的每个刷新或 ob_flush 显然都刷新了错误的缓冲区并且没有输出任何内容。所以,我想出的解决方案是在我开始发送输出之前检查一下有多少缓冲区。如果不止一个,我会刷新并关闭除一个以外的所有缓冲区。而且,令人惊讶的是,它开始起作用了。

这是我很快想出的 hacky 代码:

```
        $buffers = ob_get_status(true);

        //shows the array of how many buffers are active.
        //echo '<pre>';
        //echo 'Buffer Count: '. count($buffers).'<br>';
        //var_dump(ob_get_status(true));
        //echo '</pre>';

        if (count($buffers) > 1) {
            for ($i=0;$i<count($buffers)-1;$i++) {
                ob_end_flush();
            }
        }
```

感谢@disinfor 的回复并帮助我解决这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    • 2012-09-17
    • 2014-09-28
    • 2014-02-23
    • 1970-01-01
    相关资源
    最近更新 更多