pug-php/pug-symfony

Symfony 的 Pug 模板引擎

4.0.1 2023-03-05 23:50 UTC

README

Latest Stable Version GitHub Actions StyleCI Test Coverage

Symfony 的 Pug 模板引擎

这是当前版本 3.0 的文档。点击此处加载 2.8 版本的文档

安装

在你的 Symfony 项目根目录中,打开终端并输入。

composer require pug-php/pug-symfony

当你被要求自动安装所需设置时,输入 yes。

如果你出于任何原因,不能或不想使用它,你将不得不将它添加到你的 config/bundles.php 文件中

Pug\PugSymfonyBundle\PugSymfonyBundle::class => ['all' => true],

使用

templates 目录下创建具有 .pug 扩展名的文件来创建 Pug 视图,例如 contact.pug

h1
  | Contact
  =name

然后注入 Pug\PugSymfonyEngine 以在你的控制器中调用它

namespace App\Controller;

use Pug\PugSymfonyEngine;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;

#[AsController]
class MyController
{
    #[Route('/contact')]
    public function contactAction(PugSymfonyEngine $pug)
    {
        return $pug->renderResponse('contact/contact.pug', [
            'name' => 'Us',
        ]);
    }
}

或者,你也可以使用 \Pug\Symfony\Traits\PugRenderer 直接从控制器(或服务)的任何方法中调用 ->render()

namespace App\Controller;

use Pug\Symfony\Traits\PugRenderer;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;

#[AsController]
class MyController
{
    use PugRenderer;

    #[Route('/contact')]
    public function contactAction()
    {
        return $this->render('contact/contact.pug', [
            'name' => 'Us',
        ]);
    }
}

无论你的控制器是否扩展了 AbstractController(因为它也可以渲染 twig 视图),所以它会像以前一样工作,无论你是使用 ->render('view.html.twig') 还是 ->render('view.pug')

注意:标准 Twig 函数也适用于你的 Pug 模板,例如

!=form(form)

请参阅 https://symfony.ac.cn/doc/current/forms.html

通常从控制器将 FormView 传递

$task = new Task();
// ...

$form = $this->createFormBuilder($task)
    // ...
    ->getForm();

return $pug->renderResponse('home.pug', [
    'form' => $form->createView(),
]);

配置

你可以注入 Pug\PugSymfonyEngine 来更改选项、共享值、在路由级别添加插件到 Pug

// In a controller method
#[Route('/contact')]
public function contactAction(\Pug\PugSymfonyEngine $pug)
{
    $pug->setOptions(array(
      'pretty' => true,
      'pugjs' => true,
      // ...
    ));
    $pug->share('globalVar', 'foo');
    $pug->getRenderer()->addKeyword('customKeyword', $bar);

    return $pug->renderResponse('contact/contact.pug', [
        'name' => 'Us',
    ]);
}

如果你使用 PugRenderer 特性,你不需要再次注入服务,可以直接使用 $this->pug

可以在特定事件上全局运行,例如 onKernelView,在渲染任何视图之前应用自定义设置。

请参阅 pug-php 文档中的选项:https://phug-lang.com/#options

初始选项也可以通过 config/services.yaml 中的参数传递

# config/services.yaml
parameters:
    # ...
    pug:
        expressionLanguage: php

注意:你也可以创建一个 config/packages/pug.yaml 来存储 Pug 设置。

Twig 的全局变量在 Pug 视图中可用(例如,使用 app 变量获取 app.tokenapp.environment)以及你添加到 twig.yaml 的任何自定义全局值或服务

# config/packages/twig.yaml
twig:
    # ...
    globals:
        translator: '@translator'

使翻译器在所有视图中都可用

p=translator.trans('Hello %name%', {'%name%': 'Jack'})

传递给 globals 的键(左)是要在视图中使用的变量名称,值(右)是类名(可以是 '@\App\MyService')或解析依赖注入的别名。它也可以是静态值,例如 ga_tracking: 'UA-xxxxx-x'

如果你需要为每个 Pug 渲染应用更高级的自定义设置,你可以使用拦截器服务。

# config/services.yaml
parameters:
    # ...
    pug:
        interceptors:
            - App\Service\PugInterceptor
            # You can add more interceptors

services:
    # ...

    # They all need to be public
    App\Service\PugInterceptor:
        public: true

然后拦截器将看起来像这样

// src/Service/PugInterceptor.php
namespace App\Service;

use Pug\Symfony\Contracts\InterceptorInterface;
use Pug\Symfony\RenderEvent;
use Symfony\Contracts\EventDispatcher\Event;

class PugInterceptor implements InterceptorInterface
{
    public function intercept(Event $event)
    {
        if ($event instanceof RenderEvent) {
            // Here you can any method on the engine or the renderer:
            $event->getEngine()->getRenderer()->addKeyword('customKeyword', $bar);
            $event->getEngine()->getRenderer()->addExtension(MyPlugin::class);

            // Or/and manipulate the local variables passed to the view:
            $locals = $event->getLocals();
            $locals['foo']++;
            $event->setLocals($locals);

            // Or/and get set the name of the view that is about to be rendered:
            if ($event->getName() === 'profile.pug') {
                // if user variable is missing
                if (!isset($event->getLocals()['user'])) {
                    $event->setName('search-user.pug');
                    // Render the search-user.pug instead of profile.pug
                }
            }
        }
    }
}

作为服务,拦截器可以在其构造函数中注入任何依赖关系以在 intercept 方法中使用

class PugInterceptor implements InterceptorInterface
{
    private $service;

    public function __construct(MyOtherService $service)
    {
        $this->service = $service;
    }

    public function intercept(Event $event)
    {
        if ($event instanceof RenderEvent) {
            $event->getEngine()->share('anwser', $this->service->getAnwser());
        }
    }
}

拦截器是懒加载的,这意味着在上述示例中,如果 PugInterceptorMyOtherService 在其他地方没有使用,并且当前请求没有以 Pug 渲染(纯-Twig 视图、API 响应、WebSocket 等)结束,那么它们都不会被加载,这是一个优化仅需要在 Pug 渲染之前执行的事情的好方法。

部署

在生产环境中,你最好使用以下命令预渲染所有模板以提高性能

php bin/console assets:publish --env=prod

安全联系信息

如需报告安全漏洞,请使用Tidelift安全联系。Tidelift将协调修复和披露。