【问题标题】:PHP automatically pre- and append dynamic content to outputPHP 自动预先和附加动态内容到输出
【发布时间】:2020-05-07 21:48:59
【问题描述】:

有没有办法在文件实际输出前后自动包含内容?

为什么?例如,使用它来包含直到主要内容的所有内容(动态生成的 HTML、head、打开标签...),并且在文件运行后,再次自动关闭所有内容。

我知道ob_start 方法,但我不确定动态生成的内容是否容易以这种方式包含:

<?php
function bootstrap_page($content) {
    return "text before" . $content . "text after";
}

ob_start(bootstrap_page);
?>

但是,ob 不能用于捕获回调中包含的输出,AFAIK。因此,很难轻松地预先和附加动态生成的内容。我可以在回调函数中使用长字符串来获得静态版本的工作 - 但有没有办法更无缝地做到这一点?

换句话说,我基本上试图在我需要的任何(其他)文件之前和之后包含一个 php 文件,并且如果可能的话,减少到给定文件开头的函数调用。

我正在寻找的功能会改变这个:

<?php
bootstrap_this();
?>

<p>Lorem ipsum</p>

before.php:

<!DOCTYPE html>
<html>
  <?php include('head.php'); ?>
  <body>
    <?php if(somecondition) { ?>
    <h1>Hello, World!</h1>
    <?php } ?>

after.php:

  </body>
</html>

变成这样:

<?php
include 'before.php';
?>
<p>Lorem ipsum</p>
<?php
include 'after.php';
?>

最后变成:

<!DOCTYPE html>
<html>
  <?php include('head.php'); ?>
  <body>
    <?php if(somecondition) { ?>
    <h1>Hello, World!</h1>
    <?php } ?>
    <p>Lorem ipsum</p>
  </body>
</html>

【问题讨论】:

  • 我已经添加了一个答案,但我不确定我是否得到它。
  • @bestprogrammerintheworld 感谢您的努力。是的,您似乎无法轻松地将输出夹在当前文件之外。这也必须从另一个文件运行。
  • @bestprogrammerintheworld 谢谢!我按照我的要求做了,但这使我的代码比以前更复杂,所以我可能仍然必须选择不自己编码选项并使用某种框架。 ;)
  • 谢谢。我很高兴能帮助你......弄清楚你不应该自己编写代码;-)
  • @bestprogrammerintheworld 你可能已经给了我一个想法。我会尝试一下,也许我可以提供更新。

标签: php


【解决方案1】:

这不就是输出缓冲的用途吗?

<?php
// Start Buffer
ob_start();

// Include before
include 'before.php'; 
?>

<p>Lorem ipsum</p>

<?php
// Include after
include 'after.php';

// Get buffered output
$page = ob_get_clean();

echo $page;
?>

【讨论】:

  • 我认为 OP 知道这一点,但 IMO OP 正在寻找一种方法来制作一个函数,其中之前、内容和之后是包含的文件。
  • 在这种情况下,您的答案是一种可能的方法。
  • @davidgiesemann 是的,我知道这一点。我基本上是试图通过在文件开头调用一个函数来将 php 文件的输出夹在另外两个文件的输出之间(甚至更好:在一个文件中的给定点)。基本上是一个可怜的模板引擎。
【解决方案2】:

但是,ob 不能用于捕获回调中包含的输出,AFAIK

AFAYK 吗?会不会很难考?只要包含在 ob_start() 之后,并且代码在您选择这样做之前没有显式调用 ob_flush(),那么它将捕获输出。

我基本上试图在我需要的任何(其他)文件之前和之后包含一个 php 文件

这意味着某种类型的控制脚本调用 pre-oinclude、主要内容和 post-include。

如果 HTML(不是真的,我会回到那个)没有定义的根应该显式声明,那就没问题了。而且您遇到的问题 HTTP 也有一个结构,您可能会在这里颠覆它 - 标头位于内容之前。但是暂时不考虑这些,HTML 需要一个嵌套结构。所有标签都应该关闭。在不同文件中打开和关闭标签是一种混乱且不好的做法。

有很多技术可以提供您似乎正在寻找的最终结果 - ESI、模板和前端控制器模式都以更加结构化的方式提供了这一点。

【讨论】:

  • 不,事实上我确实测试过它——我只是不确定我是否做对了。但它导致:ob_start(): Cannot use output buffering in output buffering display handlers.
  • 并且:从技术上讲,它可以在同一个文件中完成 - 为了简单起见,我只是这样解释。
  • 我已经找到了这个问题。这就是我询问是否有其他方法可以实现这一目标的部分原因。如果我理解正确,在回调中不可能使用ob
【解决方案3】:

我不确定我看到了这个的用法,或者我是否理解正确,但如果我理解正确,你正在寻找这样的东西:

<?php
function dynamice_include($before, $content, $after) {
    $dynamic_content = '';
    $dynamic_content .= include $before . '.php';
    $dynamic_content .= $content;
    $dynamic_content .= include $after . '.php';
    return $dynamic_content;
}

用法:

$content = dynamice_include('before', 'Hello I am really cool','after');
echo $content;

在 before.php 和 after.php 中需要返回,例如

before.php
<?php
return "wow before";

after.php
<?php
return "wow after";

结果是:

wow beforeHello I am really coolwow after 

更新:

您正在寻找的似乎更像是这样的东西。输出缓冲区是 AFAIK 实现这一目标的唯一方法。

这段代码根本没有优化......(我只是在这里展示这个概念)

<?php
function dynamice_include($before, $content, $after) {
    $dynamic_content = '';

    ob_start();
    include $before . '.php';
    $dynamic_content .= ob_get_contents();
    ob_end_clean();  

    ob_start();
    include $content . '.php';
    $dynamic_content .= ob_get_contents();
    ob_end_clean();  

    ob_start();
    include $after . '.php';
    $dynamic_content .= ob_get_contents();    
    ob_end_clean();  

    return $dynamic_content;
}

$content = dynamice_include('before', 'dytest','after');
echo $content;

正如其他人所说 - 有很多平台、框架、模板引擎可以解决这个问题。您必须在当前文件内容中执行 ob_start() 和 ob_clean 才能使其正常工作。

更新 2:

在这种情况下,我获取当前文件输出缓冲区作为内容。

<?php
function dynamice_include($before, $content, $after) {
    $dynamic_content = '';

    ob_start();
    include $before . '.php';
    $dynamic_content .= ob_get_contents();
    ob_end_clean();  

    $dynamic_content .= $content;

    ob_start();
    include $after . '.php';
    $dynamic_content .= ob_get_contents();    
    ob_end_clean();  

    return $dynamic_content;
}
ob_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    feelings    
</body>
</html>
<?php
$content = ob_get_contents();
ob_end_clean();

$content = dynamice_include('before', $content, 'after');
echo $content;
?>

【讨论】:

  • 差不多,除了$content 是文件的捕获输出。等待 - 是否可以使用 include 以字符串的形式运行获取输出?如果是这样,我的问题就没用了……
  • 哦,我明白了 - 没有 before.phpafter.php 包含带有一些 php 而不仅仅是字符串的 html,所以我不能真正返回它。
  • 只需使用 file_get_contents() 获取文件内容,例如$str = file_get_contents($file);
  • @but 它不是一个静态的 html 文件——它包含一些 php 代码,用于插入一些信息并决定渲染哪些部分。我会尝试用一个简单的例子来更新我的问题......
【解决方案4】:

感谢@bestprogrammerintheworld 的帮助,我想出了这个:

function use_template($before = 'pre', $after = 'post') {
    ob_start();
    include $before . '.php';
    $pre = ob_get_contents();
    ob_end_clean();

    ob_start();
    include $after . '.php';
    $post = ob_get_contents();
    ob_end_clean();

    $bootstrap_page = function ($content) use ($pre, $post) {
        return $pre . $content . $post;
    };

    ob_start($bootstrap_page);
}

如果此函数在 php 文件的开头调用,before.phpafter.php 的输出将被存储并绑定到回调。然后,在读取所有主要输出之后,将所有内容拼凑在一起。不需要文件末尾的代码。

由于ob不能在回调中运行,bootstrap_page,必须先运行才能捕获其他文件。

【讨论】:

  • @bestprogrammerintheworld 感谢您的帮助 - 我可以让它工作!
猜你喜欢
  • 2022-11-02
  • 1970-01-01
  • 2015-05-02
  • 1970-01-01
  • 2012-08-05
  • 1970-01-01
  • 1970-01-01
  • 2020-03-28
  • 1970-01-01
相关资源
最近更新 更多