Я работаю над веб-проектом MVC, и я хотел включить компонент верхнего меню на своих страницах.
Что я пробовал:
Сначала я определил базовый вид класс для обработки выборки данных меню со слоя модели и их назначения (например, регистрации) для введенного экземпляр шаблона (не файл шаблона!). Тогда я определил все остальные Посмотреть классы как дочерние классы базовый вид учебный класс. Каждый раз детский взгляд экземпляр будет командовать экземпляр шаблона сделать конкретный файл шаблона (с данными, относящимися к детский взгляд экземпляр), данные меню уже зарегистрированы в экземпляр шаблона также будет введен в файл шаблона.
Хотя я чувствовал, что этот метод не очень хороший. Но я могу ошибаться.
Модель презентации:
Думая о другом решении, я обнаружил, что так называемые Модель презентациибудет правильным компонентом для использования при повторяющихся фрагментах (как часть уровень представления) должны быть включены в несколько веб-страниц. Как верхнее меню и / или левое меню и / или нумерация страниц и т. Д.
Но, несмотря на то, что я также читал другие статьи, а также сообщения и комментарии по этому вопросу — уже несколько дней мне все еще трудно «увидеть», где и как именно эти компоненты будут вписываться в мое веб-приложение.
Моя точка зрения:
Вот как я себе представляю реализацию этого шаблона (поддерживая соглашения о кодировании / именовании из моего текущего кода ниже):
Navigation
класс для хранения всех свойств (и поведения?), связанных с навигацией (верхнее меню, левое меню, нумерация страниц и т. д.). Экземпляры этого будут презентационные модели.FrontendView
базовый класс и ввести Navigation
экземпляр в это. FrontendView
извлекает данные меню из модель предметной области (через Navigation
сервис) и кормит Navigation
модель презентации с этим.Example
вид будет наследовать от FrontendView
, В вызванном методе этого (ниже: __invoke
), render
метод будет вызван на TemplateInterface
Например, как обычно.TemplateInterface
экземпляр должен получить модель презентации, например Navigation
экземпляр, как зависимость, так что, когда render
метод вызывается, все его свойства (например, как сказано: связанные с навигацией) считываются и вводятся в файл шаблона, наряду с другим, связанным с контентом. И, так как файл шаблона продлил бы файл макета с верхним меню, связанным с фрагментами веток, на экране появится верхнее меню.Но, поскольку я считаю, что я что-то понял неправильно, я подумал обратиться к вашему опыту. Основываясь на моем описании и приведенном ниже коде, не могли бы вы сказать мне несколько фраз или пример кода, как следует модель презентации шаблон будет интегрирован в мою структуру приложения, чтобы было показано хотя бы верхнее меню?
Большое спасибо за ваше терпение! Конечно, вы можете спросить меня о чем угодно.
Компоненты моего веб-приложения MVC:
Response
экземпляр (PSR-7) как тело сообщения. В конце вид возвращает Response
объект, для того, чтобы быть напечатанным.Определенный класс представления:
<?php
namespace Myapp\UI\Web\Application\View;
use Mylibs\Template\TemplateInterface;
use Psr\Http\Message\ResponseInterface;
use Myapp\Model\Application\Service\Navigation;
class Example {
/**
* Template.
*
* @var TemplateInterface
*/
private $template;
/**
* Navigation service.
*
* @var Navigation
*/
private $navigation;
/**
*
* @param TemplateInterface $template Template.
* @param Navigation $navigation Navigation service.
*/
public function __construct(TemplateInterface $template, Navigation $navigation) {
$this->template = $template;
$this->navigation = $navigation;
}
/**
* Invoke.
*
* @param ResponseInterface $response Response.
* @return ResponseInterface Response.
*/
public function __invoke(ResponseInterface $response) {
$body = $this->template->render('@Template/example.html.twig', [
'activeMenuItem' => 'example',
// The menu items are fetched from the domain model, through the Navigation service.
'menuItems', $this->navigation->getMenuItems(),
]);
$response->getBody()->write($body);
return $response;
}
}
Шаблон класса:
<?php
namespace Mylibs\Template\Twig;
use Mylibs\Template\TemplateInterface;
use Mylibs\Template\ContextCollectionInterface;
class Template implements TemplateInterface {
/**
* A collection of parameters to pass to the template.
*
* @var ContextCollectionInterface
*/
private $context;
/**
* Twig environment.
*
* @var \Twig_Environment
*/
private $environment;
/**
* @param \Twig_Environment $environment Twig environment.
* @param ContextCollectionInterface $context A collection of parameters to pass to the template.
*/
public function __construct(\Twig_Environment $environment, ContextCollectionInterface $context) {
$this->environment = $environment;
$this->context = $context;
}
/**
* Load and render a template.
*
* @param string $templateName Template name.
* @param array $context (optional) A list of parameters to pass to the template.
* @return string Rendered content.
*/
public function render(string $templateName, array $context = []): string {
//...
foreach ($context as $key => $value) {
$this->context->set($key, $value);
}
return $this->environment->render($templateName, $this->getContext()->all());
}
/**
* Get the collection of parameters to pass to the template.
*
* @return ContextCollectionInterface
*/
public function getContext(): ContextCollectionInterface {
return $this->context;
}
}
application.html.twig (файл макета приложения):
<!DOCTYPE html>
<html>
<head>
<!-- ... -->
{% block appTitle %}<!-- ... -->{% endblock %}
</head>
<body>
{% block appNavbar %}
<div id="navbar">
<ul>
{% block appMenuItems %}
{% for menuItem in menuItems %}
{% set activeClass = '' %}
{% if menuItem.id == activeMenuItem %}
{% set activeClass = 'active' %}
{% endif %}
<li class="{{ activeClass }}">
<a id="{{ menuItem.id }}" href="{{ menuItem.uri }}">
{{ menuItem.caption }}
</a>
</li>
{% endfor %}
{% endblock %}
</ul>
</div>
{% endblock %}
{% block appPageHeaderTitle %}<!-- ... -->{% endblock %}
{% block appContent %}<!-- ... -->{% endblock %}
{% block appFooter %}<!-- ... -->{% endblock %}
</body>
</html>
example.html.twig (конкретный файл шаблона, расширяющий файл макета приложения):
{% extends '@Layout/application.html.twig' %}
{% block appTitle %}
Example
{% endblock %}
{% block appPageHeaderTitle %}
Example
{% endblock %}
Задача ещё не решена.
Других решений пока нет …