Я новичок в Twig и должен проверить, является ли способ, которым я использую его в своем MVC, «правильный» способ. У меня есть ощущение, что это не так;
Я хочу иметь контроллер для каждого региона на моем сайте, и каждый контроллер должен отображать свой собственный шаблон ветки. Я читал о включении шаблонов веток в шаблоны веток, такие как:
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 в переменных, а затем рендеринг снова.
Если то, что я пытаюсь достичь, возможно, лучше, пожалуйста, дайте мне знать.
Я думаю, что это вызывает много накладных расходов, так как вам всегда нужно будет копировать / вставлять регионы всякий раз, когда вы хотите создать новую страницу / контроллер. Идеально было бы использовать основной шаблон с включениями и позволить вашим представлениям расширяться от базового.
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 %}
Если вы хотите иметь контроллер для каждого региона, вы можете создать вспомогательный класс, который вызывает все необходимые вам контроллеры, возвращая многомерный массив, определенный именем класса региона.
Таким образом, ваши переменные никогда не столкнутся, так как вы можете получить к ним доступ, например, main.title / menu.title / title
(код — просто псевдокод, не тестировал / не запускал его, просто чтобы дать вам представление)
<?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',
];
}
Других решений пока нет …