Получить абсолютный путь в Slim 4 + Twig

110
21 апреля 2022, 09:00

Всем привет! Решил переехать на Slim Framework 4. Возникла проблема. В twig-шаблоне нужно получить полный путь сайта, например, http://example.com.
Собственно, возникла проблема, что не знаю, как это можно сделать.
Увидел в slim-twig такой фрагмент кода:

$scheme = $uri->getScheme();
$authority = $uri->getAuthority();
$protocol = ($scheme ? $scheme . ':' : '') . ($authority ? '//' . $authority : '');

Где $protocol - как раз содержится нужный мне http://example.com.
Теперь думаю, как его можно применить в решении моей задачи.
Возможно, стоит создать какой-нибудь middleware.

Если есть хорошее элегантное решение, подскажите, пожалуйста.
P.S.: Конечно, можно использовать просто захардкоженый полный путь сайта, но, думаю, что есть более хорошие варианты.

Answer 1

Я создал расширение для twig

<?php
declare(strict_types=1);
namespace App\Support\Twig;
use Closure;
use Psr\Http\Message\UriInterface;
use Slim\Interfaces\RouteParserInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
final class RouteExtension extends AbstractExtension
{
    /**
     * @var RouteParserInterface
     */
    private $router;
    /**
     * @var UriInterface
     */
    private $uri;
    public function __construct(RouteParserInterface $router, UriInterface $uri)
    {
        $this->router = $router;
        $this->setUri($uri);
    }
    public funstion setUri(UriInterface $uri)
    {
        $this->uri = $uri;
    }
    public function getFunctions(): array
    {
        return  [
            new TwigFunction('route', Closure::fromCallable([$this, 'route'])),
        ];
    }
    private function route(string $route, array $params = [], array $query = [], bool $absolute = false): string
    {
        if ($absolute) {
            $this->router->fullUrlFor($this->uri, $route, $params, $query);
        }
        return $this->router->urlFor($route, $params, $query);
    }
}

И в контейнере при билдинге twig добавляю это расширение (тут уже реализация от конкретного контейнера зависит)

$options = [
    'cache' => $container->get('dir.cache.twig'),
];
$twig = new Environment(
    $container->get(Twig\Loader\LoaderInterface::class),
    $options
);
$twig->addExtension($container->get(App\Support\Twig\RouteExtension::class));

Т.к. у меня приложение работает на нескольких доменах, в контейнере я создаю экземпляр с объектом Uri из конфигурации (дефолтный), а в миддлваре передаю объект из запроса:

<?php
declare(strict_types=1);
namespace App\Middleware;
use App\Support\Twig\RouteExtension;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
final class TwigRouteExtensionMiddleware implements MiddlewareInterface
{
    /**
     * @var RouteExtension
     */
    private $extension;
    public function __construct(RouteExtension $extension)
    {
        $this->extension = $extension;
    }
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $this->extension->setUri($request->getUri());
        return $handler->handle($request);
    }
}

И в шаблонах строю урл по роутингу

{% extends 'layout.twig' %}
{% block content %}
<a href="{{ route('home') }}">Home</a>
<a href="{{ route('privacy_policy', {}, {}, true) }}">Privacy Policy</a>
{% endblock %}
READ ALSO
Получить товары по значению свойства

Получить товары по значению свойства

Доброго времени суток

229
Не работает пагинация на странице

Не работает пагинация на странице

Есть архив news, странице даю такой же slug и не работает пагинацияКак это пофиксить, чтобы не менять название архива и слаг страницы остался...

203