在 Slim Framework 中管理跨多个路由共享的数据的最佳方法是什么?
What is the best way to manage data shared across multiple routes in Slim Framework?
假设您有 3 个页面、3 个路由(/index
、/about
、/contact
)和一个显示从数据库检索的项目列表的共享 header .
在 Slim 中是否有更好的方法来检索所有 pages/routes 的这些项目,以传递给相应的模板,而不是基本上为每个路由控制器方法复制代码?
例如,除此之外还有其他方式吗?
$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) */
]);
});
一种选择是将这些项目作为全局变量添加到 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']);
});
共享相同数据的路由也可以使用相同的响应器来呈现内容。
伪例子:
<?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']);
});
假设您有 3 个页面、3 个路由(/index
、/about
、/contact
)和一个显示从数据库检索的项目列表的共享 header .
在 Slim 中是否有更好的方法来检索所有 pages/routes 的这些项目,以传递给相应的模板,而不是基本上为每个路由控制器方法复制代码?
例如,除此之外还有其他方式吗?
$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) */
]);
});
一种选择是将这些项目作为全局变量添加到 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']);
});
共享相同数据的路由也可以使用相同的响应器来呈现内容。
伪例子:
<?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']);
});