twig:首先渲染子模板,然后传递给父模板
twig: rendering child templates first, then passing to parent template
我是 Twig 的新手,需要检查我在 MVC 中使用它的方式是否是 'correct' 方式。我有一种感觉,它不是;
我想为我站点中的每个区域设置一个控制器,并让每个控制器呈现它们自己的树枝模板。我阅读了有关在 twig 模板中包含 twig 模板的信息,例如:
main.twig
{% include 'header.twig' %}
{% include 'menu.twig' %}
{% include 'content.twig' %}
{% include 'footer.twig' %}
这个问题是我无法 运行 在包含模板之前为每个区域设置单独的控制器。我必须将所有区域的变量一次传递给 main.twig,但我不喜欢这样做。
所以我现在执行以下操作:
$regions=[];
//...preprocessing menu items here in a controller...
$template=$twig->loadTemplate('regions/menu.twig');
$regions['menu'] = $template->render(array(
'home' => 'Go to Home',
'contact' => 'Contact page'
));
//...other regions...
$template=$twig->loadTemplate('main.twig');
echo $template->render([
'regions'=>$regions
]);
然后使用原始值打印 main.twig 内的区域:{{regions.menu|raw}}
这样我就可以完全控制传递到每个模板的数据,这正是我想要的。但是我觉得我现在没有按照预期的方式使用 Twig,因为我将渲染 html 保存在变量中,然后再次渲染它。
如果我试图以更好的方式实现,请告诉我。
我认为这会造成大量开销,因为无论何时您想要创建新 page/controller,您总是需要 copy/paste 区域。理想情况下是使用包含包含的主模板,并让您的视图从基础模板扩展。
base.twig.html
<!DOCTYPE html>
<html>
<head>
<title>{{ page.title | default('') }}</title>
<link rel="stylesheet" type="text/css" href="default.css" />
{% block css %}
{% endblock %}
</head>
<body>
{% block nav %}
<nav id="main">
{% for link in main.links %}
<a href="{{ link.url }}">{{ link.title }}</a>
{% endfor %}
</nav>
{% endblock %}
<div id="content">
{% block content %}
{% endblock %}
</div>
{% block javascript %}
{% endblock %}
</body>
</html>
{% extends "base.twig.html" %}
{% block content %}
<h1>{{ title }}</h1>
{% endblock %}
如果你想为每个区域都有一个控制器,你可以创建一个助手 class,它调用你需要的所有控制器,返回一个由 class 名称定义的 multi-dimensional 数组该地区的。
这样你的变量就永远不会发生冲突,因为你可以通过例如访问它们。 main.title / menu.title / 标题
(代码只是pseudo-code,没有test/run,只是给大家一个思路)
<?php
$regions = (new \Project\Regions\Container())->addRegion('Main')
->addRegion('Menu');
echo $twig->render('child.html', array_merge($regions->getParameters(), [
'title' => 'Hello World',
]);
class Container {
private $regions = [];
public function __construct($regions = []) {
$this->regions = $regions;
}
public function setRegions($regions = []) {
$this->regions = $regions;
return $this;
}
public function addRegion($region) {
if (!in_array($region, $this->regions)) $this->regions[] = $region;
return $this;
}
public function getParameters() {
$data = [];
foreach($this->regions as $region) {
$class = '\Project\Regions\'.$region;
if (!class_exists($class)) continue;
$data[strtolower($region)] = (new $class())->getParameters();
}
return $data;
}
}
<?php
namespace Project\Regions;
abstract class Region {
public function getParameters() {
return [];
}
}
<?php
namespace Project\Regions;
class Page extends Region {
public function getParamters() {
return [
'title' => 'foo',
];
}
}
<?php
namespace Project\Regions;
class Menu extends Region {
return [
'title' => 'bar',
];
}
我是 Twig 的新手,需要检查我在 MVC 中使用它的方式是否是 'correct' 方式。我有一种感觉,它不是;
我想为我站点中的每个区域设置一个控制器,并让每个控制器呈现它们自己的树枝模板。我阅读了有关在 twig 模板中包含 twig 模板的信息,例如:
main.twig
{% include 'header.twig' %}
{% include 'menu.twig' %}
{% include 'content.twig' %}
{% include 'footer.twig' %}
这个问题是我无法 运行 在包含模板之前为每个区域设置单独的控制器。我必须将所有区域的变量一次传递给 main.twig,但我不喜欢这样做。
所以我现在执行以下操作:
$regions=[];
//...preprocessing menu items here in a controller...
$template=$twig->loadTemplate('regions/menu.twig');
$regions['menu'] = $template->render(array(
'home' => 'Go to Home',
'contact' => 'Contact page'
));
//...other regions...
$template=$twig->loadTemplate('main.twig');
echo $template->render([
'regions'=>$regions
]);
然后使用原始值打印 main.twig 内的区域:{{regions.menu|raw}}
这样我就可以完全控制传递到每个模板的数据,这正是我想要的。但是我觉得我现在没有按照预期的方式使用 Twig,因为我将渲染 html 保存在变量中,然后再次渲染它。
如果我试图以更好的方式实现,请告诉我。
我认为这会造成大量开销,因为无论何时您想要创建新 page/controller,您总是需要 copy/paste 区域。理想情况下是使用包含包含的主模板,并让您的视图从基础模板扩展。
base.twig.html
<!DOCTYPE html>
<html>
<head>
<title>{{ page.title | default('') }}</title>
<link rel="stylesheet" type="text/css" href="default.css" />
{% block css %}
{% endblock %}
</head>
<body>
{% block nav %}
<nav id="main">
{% for link in main.links %}
<a href="{{ link.url }}">{{ link.title }}</a>
{% endfor %}
</nav>
{% endblock %}
<div id="content">
{% block content %}
{% endblock %}
</div>
{% block javascript %}
{% endblock %}
</body>
</html>
{% extends "base.twig.html" %}
{% block content %}
<h1>{{ title }}</h1>
{% endblock %}
如果你想为每个区域都有一个控制器,你可以创建一个助手 class,它调用你需要的所有控制器,返回一个由 class 名称定义的 multi-dimensional 数组该地区的。 这样你的变量就永远不会发生冲突,因为你可以通过例如访问它们。 main.title / menu.title / 标题
(代码只是pseudo-code,没有test/run,只是给大家一个思路)
<?php
$regions = (new \Project\Regions\Container())->addRegion('Main')
->addRegion('Menu');
echo $twig->render('child.html', array_merge($regions->getParameters(), [
'title' => 'Hello World',
]);
class Container {
private $regions = [];
public function __construct($regions = []) {
$this->regions = $regions;
}
public function setRegions($regions = []) {
$this->regions = $regions;
return $this;
}
public function addRegion($region) {
if (!in_array($region, $this->regions)) $this->regions[] = $region;
return $this;
}
public function getParameters() {
$data = [];
foreach($this->regions as $region) {
$class = '\Project\Regions\'.$region;
if (!class_exists($class)) continue;
$data[strtolower($region)] = (new $class())->getParameters();
}
return $data;
}
}
<?php
namespace Project\Regions;
abstract class Region {
public function getParameters() {
return [];
}
}
<?php
namespace Project\Regions;
class Page extends Region {
public function getParamters() {
return [
'title' => 'foo',
];
}
}
<?php
namespace Project\Regions;
class Menu extends Region {
return [
'title' => 'bar',
];
}