Как внедрить шаблон Presentation Model в веб-MVC — для отображения верхнего меню

Я работаю над веб-проектом MVC, и я хотел включить компонент верхнего меню на своих страницах.

Что я пробовал:

Сначала я определил базовый вид класс для обработки выборки данных меню со слоя модели и их назначения (например, регистрации) для введенного экземпляр шаблона (не файл шаблона!). Тогда я определил все остальные Посмотреть классы как дочерние классы базовый вид учебный класс. Каждый раз детский взгляд экземпляр будет командовать экземпляр шаблона сделать конкретный файл шаблона (с данными, относящимися к детский взгляд экземпляр), данные меню уже зарегистрированы в экземпляр шаблона также будет введен в файл шаблона.

Хотя я чувствовал, что этот метод не очень хороший. Но я могу ошибаться.

Модель презентации:

Думая о другом решении, я обнаружил, что так называемые Модель презентациибудет правильным компонентом для использования при повторяющихся фрагментах (как часть уровень представления) должны быть включены в несколько веб-страниц. Как верхнее меню и / или левое меню и / или нумерация страниц и т. Д.

Но, несмотря на то, что я также читал другие статьи, а также сообщения и комментарии по этому вопросу — уже несколько дней мне все еще трудно «увидеть», где и как именно эти компоненты будут вписываться в мое веб-приложение.

Моя точка зрения:

Вот как я себе представляю реализацию этого шаблона (поддерживая соглашения о кодировании / именовании из моего текущего кода ниже):

  • Я определяю Navigation класс для хранения всех свойств (и поведения?), связанных с навигацией (верхнее меню, левое меню, нумерация страниц и т. д.). Экземпляры этого будут презентационные модели.
  • Я определяю FrontendView базовый класс и ввести Navigation экземпляр в это. FrontendView извлекает данные меню из модель предметной области (через Navigation сервис) и кормит Navigation модель презентации с этим.
  • Example вид будет наследовать от FrontendView, В вызванном методе этого (ниже: __invoke), render метод будет вызван на TemplateInterface Например, как обычно.
  • И вот я застрялТеоретически, я считаю, что также TemplateInterface экземпляр должен получить модель презентации, например Navigation экземпляр, как зависимость, так что, когда render метод вызывается, все его свойства (например, как сказано: связанные с навигацией) считываются и вводятся в файл шаблона, наряду с другим, связанным с контентом. И, так как файл шаблона продлил бы файл макета с верхним меню, связанным с фрагментами веток, на экране появится верхнее меню.

Но, поскольку я считаю, что я что-то понял неправильно, я подумал обратиться к вашему опыту. Основываясь на моем описании и приведенном ниже коде, не могли бы вы сказать мне несколько фраз или пример кода, как следует модель презентации шаблон будет интегрирован в мою структуру приложения, чтобы было показано хотя бы верхнее меню?

Большое спасибо за ваше терпение! Конечно, вы можете спросить меня о чем угодно.


Компоненты моего веб-приложения MVC:

  • модель предметной области состоит из сервисов, сущностей, картографов данных и т. д.
  • контроллер Экземпляр обновляет уровень модели через соответствующие сервисы.
  • просмотреть экземпляр извлекает обновленные данные из модели предметной области, в том числе через службы, и подготавливает / форматирует их для представления. Далее, представление использует экземпляр шаблона сделать конкретный файл шаблона, передав ему подготовленные данные. Визуализированный контент будет передан представлению Response экземпляр (PSR-7) как тело сообщения. В конце вид возвращает Response объект, для того, чтобы быть напечатанным.
  • экземпляр шаблона использует шаблонизатор составная часть (прут) — зависимость для отображения заданного файла шаблона с заданными данными.
  • Все зависимости управляются контейнером внедрения зависимостей (PHP-DI).
  • контроллер и Посмотреть вызываются отдельно. Итак контроллер не знает о Посмотреть.

Определенный класс представления:

<?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 %}

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]