包装后的未定义变量包含在PHP中

时间:2014-05-25 01:44:51

标签: php

我正在使用PHP进行Web开发。我正在使用以下函数来包装视图的include

<?php
function render($templateFile) {
    $templateDir = 'views/';
    if (file_exists($templateDir . $templateFile)) {
        include $templateDir . $templateFile;
    } else {
        throw new Exception("Template '{$templateFile}' couldn't be found " .
           "in '{$templateDir}'");
    }
}
?>

虽然这对我来说似乎是正确的,但是有一个非常意外的行为:当我将某个变量定义为某个东西(例如数组)并使用render来包含使用该变量的视图时,我得到一个{{ 1}}错误。但是,当我明确地使用undefined variable时,根本没有错误,事情就好了。

这是调用include的脚本:

render

这是使用<?php include 'lib/render.php'; // Includes the function above. $names = array('Trevor', 'Michael', 'Franklin'); render('names.html'); // Error, but "include 'views/names.html'" works fine. ?> 变量的文件:

$names

非常感谢帮助。

2 个答案:

答案 0 :(得分:2)

这是来自include函数的PHP文档(c.f。http://us1.php.net/manual/en/function.include.php):

  

当包含文件时,它包含的代码会继承该变量   包含发生的行的范围。任何可用的变量   在调用文件中的那一行将在被调用的内容中可用   文件,从那时起。但是,所有功能和类   在包含文件中定义的具有全局范围。

还有:

  

如果include发生在调用文件中的函数内,那么   调用文件中包含的所有代码都将表现得像它一样   已在该功能内定义。所以,它将遵循变量   该职能的范围。

因此,如果您的render函数无法访问$names,那么您所包含的文件也不会。

一种可能的解决方案是将您希望能够在视图模板中访问的参数传递给render函数。所以,像这样:

function render($templateFile, $params=array()) {
    $templateDir = 'views/';
    if (file_exists($templateDir . $templateFile)) {
        include $templateDir . $templateFile;
    } else {
        throw new Exception("Template '{$templateFile}' couldn't be found " .
           "in '{$templateDir}'");
    }
}

然后,像这样传递它们:

$names = array('Trevor', 'Michael', 'Franklin');

render('names.html', array("names" => $names));

并在您的视图模板中使用它们:

<html>
  <head>
    <title>Names</title>
  </head>
  <body>
    <ol>
    <?php foreach ($params['names'] as $name): ?>
      <li><?php echo $name; ?></li>
    <?php endforeach; ?>
    </ol>
  </body>
</html>

可能有更好的解决方案,例如将render函数放入View类。然后,您可以从模板文件中调用View类函数,并以这种方式访问​​参数,而不是假设视图模板范围中将有$params变量。但是,这是最简单的解决方案。

答案 1 :(得分:1)

问题是,当您使用include 'views/names.html'直接包含文件时,变量$name仍保留在同一文件范围内。因此,它的工作原理。但是当include通过函数完成时, varibale $name仍然超出函数内的范围。所以它不起作用。例如,在函数内声明$names为全局,它将起作用。

如果您更新下面的功能,您会看到$names变量有效。

function render($templateFile) {

    global $names; // declares the global $names variable to use in the included files

    $templateDir = 'views/';
    if (file_exists($templateDir . $templateFile)) {
        include $templateDir . $templateFile;
    } else {
        throw new Exception("Template '{$templateFile}' couldn't be found " .
           "in '{$templateDir}'");
    }
}