如何让php有效地循环模板文件

时间:2016-11-21 13:45:51

标签: php

我发现了关于在PHP中加载模板文件的堆栈溢出的问题,这很好,但我希望循环一行的模板文件,多次。 我读过的文章就在这里 [PHP Content Separation。 该页面上的最佳答案来自prodigitalson和他的函数GetTemplate。

现在我想使用这样的东西,但是如果我把它的功能放在循环中那么它就不会非常有效,因为它会多次加载同一个文件。

所以我尝试了这个。我会得到html包括在内。然后将它存储在变量中,然后将其放入循环中。但它没有用。

这是我的代码。数据已经在一个名为$ result的数组中。

$salesTemp=$this->tempLine('salesTEM.php');
while($row = array_shift($result)):
    echo $salesTemp;
endwhile;

private function tempLine($file){
    ob_start();
    require $file;
    return ob_get_clean();
}

问题是我的变量没有在模板中更新。 这是我的模板

<li class="list-group-item"><?php echo $Customer;?><span class="label label-primary pull-right">SALES</span></li>

有没有办法重写这个,所以我的$ Customer变量已更新。

我这样做是为了尝试将php和html分开。

3 个答案:

答案 0 :(得分:1)

我看到代码的主要问题是当声明$salesTemp并通过tempLine()方法运行时,会返回一个字符串(由于ob_get_clean())。模板中的变量已经解析,当循环中回显字符串时,模板中的变量不会更新,因为它们已经被解析并处理成字符串。为了解决这个问题,我会:

while ($row = array_shift($result)) {

    echo $this->tempLine('salesTEM.php', $Customer);
}

/**
 * @return string
 */
private function tempLine($file, $Customer) {

    ob_start();
    require $file;
    return ob_get_clean();
}

这将是获得你想要的最短途径。如果您希望不在每次迭代中包含模板,请尝试:

$salesTEM = include 'salesTEM.php';

while ($row = array_shift($result)) {

    echo sprintf($salesTEM, $Customer);
}

/**
 * salesTEM.php
 */
<li class="list-group-item">
    %s
    <span class="label label-primary pull-right">SALES</span>
</li>

有许多框架可以提供开箱即用的功能,并且可以用于获取有关模板技术的其他信息。从本质上讲,通过函数(文件名和数据)传递信息总是很好的形式,并期望字符串退出。它也使单元测试变得容易。允许它被动地获取信息往往会使代码容易出错,例如:

while ($row = array_shift($result)) {

    echo include 'salesTEM.php';
}

/**
 * salesTEM.php
 */
<li class="list-group-item">
    <?php echo $Customer;?>
    <span class="label label-primary pull-right">SALES</span>
</li>

您可能会意外地包含该文件,并且未声明$Customer变量导致难以发现的错误。定义所有进出的内容,这将使其在未来更容易管理。

答案 1 :(得分:0)

您应该将循环移动到模板文件中,因为您已经使用PHP作为其中的模板语言。这将使您的工作变得更加轻松,并为您提供最佳性能(无需重写整个模板系统)。

关于保持HTML和PHP分离的说法:它实际上不太准确,因为它是从原始目标的微妙重写。即将业务代码和演示文稿代码分开 通常,表示代码是纯HTML,但在动态网站的情况下,表示代码也需要动态元素。大多数情况下,这是通过使用提供自己的模板语言的模板引擎来解决的,但PHP也可以作为一个使用。事实上,PHP最初是作为模板语言开始的。 :)

因此,在您的视图中使用PHP非常好。前提是所说的PHP代码只控制输出,而不是业务操作。

答案 2 :(得分:0)

我有一个有效的答案。然而正如ChristianF所说,这可能不是最好的答案,但这确实解决了我的问题。

正确而不是在html中使用echo我将标记放在%%中,如此

<li class="list-group-item">%CUSTOMER%<span class="label label-primary pull-right">SALES</span></li>

然后是我课堂上的循环。我可以在上一行中构建对象以获得更好的可读性,或者像我一样内联它。

$salesTemp=$this->tempLine('salesTEM.php');
while($row = array_shift($result)):
    echo $this->replaceTemp($salesTemp, $obj=(object)array ( 'CUSTOMER' => $row['CustomerName'] ));
endwhile;

和一个小功能

private function replaceTemp($file, $obj){
    return preg_replace('~%(\w+)%~e', '$obj->$1', $file);
}
private function tempLine($file){
    ob_start();
    require $file;
    return ob_get_clean();
}

该函数基本上替换了html中的所有内容,其中有%%符号与对象中的任何内容。

<强>更新 在发布这个之后我已经改进了我的答案,但是我会把它留在那里,因为这是我原来的答案。以下是改进上述答案的课程。在rTemplate函数中,我可以有一个或多个将在模板中替换的标记。对于示例,我只需要替换一个标记,但您可以添加许多标记。运行testLoad将列出数组,获取模板并使用rTemplate中的内容填充标记。

class testlist{
    private $myfile;

    public function __construct(){
        $this->myfile=$this->loadTemplate('salesTEM.php');
    }

    public function testload(){
        // At this point the array is populated from a database, but I haven't shown this.
        // You can populate the array anyway you like.
        while($row = array_shift($result)):
            echo $this->rTemplate($row['CustomerName']);
        endwhile;

    }

    // This loads in a file into a string and then returns it.
    private function loadTemplate($file){
        ob_start();
        require $file;
        return ob_get_clean();
    }

    // This makes the object to replace keywords, then replaces them
    private function rTemplate($customer)
    {
        $obj = (object) array(
            'CUSTOMER' => $id           
        );
        return preg_replace('~%(\w+)%~e', '$obj->$1', $this->myfile);
    }
}