Как лучше всего управлять данными, передаваемыми по нескольким маршрутам в Slim Framework? - PullRequest
0 голосов
/ 04 августа 2020

Предположим, у вас есть 3 страницы, 3 маршрута (/index, /about, /contact) и общий заголовок, который отображает список элементов, полученных из базы данных.

Есть ли лучший способ в Slim, чтобы получить эти элементы для всех страниц / маршрутов, передать в соответствующие шаблоны, в отличие от репликации кода для каждого метода контроллера маршрута?

например, любым другим способом, кроме этого?

$app->get('/', function ($request, $response, $args) {
    return $this->view->render($response, 'index.twig', [
        'items' => /* retrieve items from database */
    ]);
});

$app->get('/about', function ($request, $response, $args) {
    return $this->view->render($response, 'about.twig', [
        'items' => /* retrieve items from database (duplicate code) */
    ]);
});

$app->get('/contact', function ($request, $response, $args) {
    return $this->view->render($response, 'contact.twig', [
        'items' => /* retrieve items from database (duplicate code) */
    ]);
});

Ответы [ 2 ]

1 голос
/ 07 августа 2020

Маршруты, использующие одни и те же данные, также могут использовать один и тот же респондент для рендеринга содержимого.

Псевдо-пример:

<?php

namespace App\Responder;

use Psr\Http\Message\ResponseInterface;
use Slim\Views\Twig;

final class Responder
{
    private $twig;

    public function __construct(Twig $twig)
    {
        $this->twig = $twig;
    }

    public function render(ResponseInterface $response, string $template, array $data = []): ResponseInterface
    {
        $shared = ['item1', 'item2'];
        $data = array_replace(shared, $data);

        return $this->twig->render($response, $template, $data);
    }
}

Использование

$this->responder->render($response, 'index.twig', ['page' => 'content']);

или. ..

use App\Responder\Responder;

// ...

$app->get('/index', function($request, $response, $args){
    return $this->get(Responder::class)->render($response, 'index.twig', ['pagecontent' => 'This is some content for /index only']);
});

$app->get('/about', function($request, $response, $args){
    return $this->get(Responder::class)->render($response, 'about.twig', ['pagecontent' => 'You can have custom content for /about']);
});

$app->get('/contact', function($request, $response, $args){
    return $this->get(Responder::class)->render($response, 'contact.twig', ['pagecontent' => '...and /contact as well']);
});
1 голос
/ 07 августа 2020

Один из вариантов - добавить эти элементы в качестве глобальных переменных в TwigEnvironment, чтобы они были доступны в каждом шаблоне.

Сначала вам нужно добавить глобальные переменные в среду Twig:

// A simple items provider which helps you generate a list of items
// You can change this to something that reads the items from database, etc.
class ItemsProvider {
    public function getItems()
    {
        return ['item 1', 'item 2', 'item 3', 'item-4', ];
    }
}

// Set view in Container
$container->set('view', function($c) {
    $twig = Twig::create('<path-to-tiwg-templates'>);
    // get items from items-provider and add them as global `items` variable
    // to all twig templates
    $twig->getEnvironment()->addGlobal('items', $c->get('items-provider')->getItems());
    return $twig;
});

// set sample items, you can modifiy this 
$container->set('items-provider', function($c){
    return new ItemsProvider;
});

Теперь переменная items доступна для каждого шаблона Twig без необходимости явно передавать ее методу render:

layout.twig :

These are some items available in every twig template:<br>
<ul>
{% for item in items%}
    <li>{{ item }}</li>
{% endfor %}
</ul>
<br>
And this is some page specific content:<br>
{% block content %}
    {{ pagecontent }}
{% endblock %}

Все три шаблона index.twig, about.twig и contact.twig могут расширять layout.twig :

{% extends 'layout.twig' %}

Определения маршрутов с другим значением для каждого маршрута для той же переменной, используемой в layout.twig :

$app->get('/index', function($request, $response, $args){
    return $this->get('view')->render($response, 'index.twig', ['pagecontent' => 'This is some content for /index only']);
});

$app->get('/about', function($request, $response, $args){
    return $this->get('view')->render($response, 'about.twig', ['pagecontent' => 'You can have custom content for /about']);
});

$app->get('/contact', function($request, $response, $args){
    return $this->get('view')->render($response, 'contact.twig', ['pagecontent' => '...and /contact as well']);
});
...