来自PHP 手册include
:
当一个文件被包含时,它包含的代码继承了包含发生的行的变量范围。从那时起,调用文件中该行的任何可用变量都将在被调用文件中可用。但是,包含文件中定义的所有函数和类都具有全局范围。
当你这样做
public function somethingAction() {
$someVariable = "something";
$this->render('someLayout');
}
$someVariable
变量仅限于范围somethingAction()
。调用您的render()
方法不会神奇地使变量在 中可用render()
,因为该render()
方法具有自己的变量范围。一个可能的解决方案是
public function somethingAction() {
$this->render(
'someLayout',
array(
'someVariable' => 'something'
)
);
}
然后更改render()
为
public function render($Layout, array $viewData) {
$this->Layout = $Layout;
include( ... .php)
}
然后,您将可以访问$viewData
包含的文件,前提是您没有尝试在其他功能或方法中使用它,例如,如果您的包含文件如下所示:
<h1><?php echo $viewData['someVariable']; ?></h1>
它会起作用,但如果它看起来像这样:
function foo() {
return $viewData['someVariable'];
}
echo foo();
它不起作用,因为foo()
它有自己的变量范围。
但是,控制器的唯一职责是处理输入。渲染是视图的责任。因此,您的控制器根本不应该有render()
方法。考虑将该方法移至您的 View 类,然后执行
public function somethingAction() {
$view = new View('someLayout');
$view->setData('someVariable', 'something');
$view->render();
}
render()
然后可以像这样实现 View 对象的方法:
class View
…
$private $viewData = array();
public function setData($key, $value)
{
$this->viewData[$key] = $data;
}
public function render()
{
extract($this->viewData, EXTR_SKIP);
include sprintf('/path/to/layouts/%s.php', $this->layout);
}
该extract
函数将使用它们的键作为名称在当前范围内导入数组的值。这将允许您使用viewData
as$someVariable
而不是$this->viewData['someVariable']
. extract
不过,请确保您在使用它之前了解其安全隐患。
请注意,这只是您当前做事方式的一种可能替代方案。您也可以将视图完全从控制器中移出。