umanit/block-bundle

简化 Doctrine 块管理

安装次数: 9,859

依赖者: 1

建议者: 0

安全: 0

星级: 6

关注者: 9

分支: 5

开放问题: 4

类型:symfony-bundle

3.1.1 2024-02-09 11:02 UTC

README

简化 Doctrine 块管理。

  • 简单实现
  • 灵活
  • 可排序的块
  • 数据库一致性
  • 用户友好
  • 开发者友好

哲学

通常在处理块时,由于需要在单个表中存储许多块类型,开发者会丢失数据库一致性。在单个表中存储多种类型块的最常见方式是将它们存储在 json 列中。

我们认为 json 对数据库一致性和性能不好。搜索、索引、管理关系、主键和唯一键等,没有一个是与 json 兼容的。

UmanitBlockBundle 通过将实体归还给开发者来解决这个问题。

前端要求

安装

将包注册到 config/bundles.php

<?php

return [
    // ...
    Umanit\BlockBundle\UmanitBlockBundle::class => ['all' => true],
];

添加 Twig 的一个表单主题

# config/packages/twig.yaml
twig:
    form_themes:
        # When using Sylius
        - '@UmanitBlock/sylius/form/panel.html.twig'
        # Read further for integration with EasyAdmin 4

package.json 中添加 @umanit/block-bundle 开发依赖。如果您的项目使用 Flex,这部分会自动完成。

{
  //...
  "devDependencies": {
    // ...
    "@umanit/block-bundle": "file:vendor/umanit/block-bundle/Resources/assets"
  }
}

将刺激控制器添加到 assets/controllers.json。如果您的项目使用 Flex,这部分会自动完成。

{
  "controllers": {
    // ...
    "@umanit/block-bundle": {
      "blocks": {
        "enabled": true,
        "fetch": "eager"
      },
      "item": {
        "enabled": true,
        "fetch": "eager"
      },
      "sortable": {
        "enabled": true,
        "fetch": "eager"
      }
    }
  }
  // ...
}

不要忘记安装 JavaScript 依赖项并编译

yarn install --force
yarn encore dev

警告

如果您想使用此包,则必须在您的后端运行 Stimulus 应用程序:确保导入启动它的 bootstrap.js 文件。您的脚本必须使用 encore_entry_script_tags() 加载。

以下是根据您的后端库如何操作的示例,假设您的末端有一个 admin.js 文件

EasyAdmin 4

在您的 DashboardController 中,您可以这样做

class DashboardController extends AbstractDashboardController
{   
    public function configureAssets(): Assets
    {
        return parent::configureAssets()
                     ->addWebpackEncoreEntry('admin')
        ;
    }
}

Sonata Admin 4

配置

sonata_admin:
    templates:
        form_theme:
            - 'admin/sonata_form_theme.html.twig'
    assets:
        extra_javascripts:
            - 'build/admin/app.js'
  • app.js 需要导入您的 bootstrap.js,它加载您自己的 Stimulus 控制器和块包在您的 Stimulus 后端应用程序中的那些

您需要修改 webpack.config.js 以允许您的 Stimulus 控制器在您的 Sonata 后端中工作

// DO
Encore.disableSingleRuntimeChunk();

// DON'T
Encore
  .splitEntryChunks()
  .enableSingleRuntimeChunk();

用法

术语

  • 是一个简单的 Doctrine 实体,它实现了 Umanit\BlockBundle\Model\BlockInterface
  • 块管理器 是一个用于管理和渲染 的服务。
  • 面板 是一个包含有序 实例集合的 Doctrine 实体。

创建包含面板的实体

通常,您将有一个内容实体(在此我们将其称为 Page),它有一个或多个 Panels

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Umanit\BlockBundle\Entity\Panel;

/**
 * @ORM\Entity()
 */
 #[ORM\Entity]
class Page
{
    // Your other fields...
    
    /**
     * @var Panel
     *
     * @ORM\ManyToOne(targetEntity="Umanit\BlockBundle\Entity\Panel", cascade={"persist"})
     * @ORM\JoinColumn(name="panel_id", referencedColumnName="id")
     */
    #[ORM\ManyToOne(targetEntity: 'Umanit\BlockBundle\Entity\Panel', cascade: ['persist'])]
    #[ORM\JoinColumn(name: 'panel_id', referencedColumnName: 'id')]
    protected $content;
    
    // Getters and Setters...
}

接下来,使用提供的 PanelType 表单来管理 Page 内容。

use Umanit\BlockBundle\Form\PanelType;

$builder->add('content', PanelType::class);

默认情况下,每个块管理器都是可用的。如果想要过滤它们,可以提供一个选项 authorized_blocks,这是一个包含所有允许选择的块类型的数组,或者 unauthorized_blocks,这是一个包含所有不允许选择的块类型的数组。

use Umanit\BlockBundle\Form\PanelType;

$builder->add('content', PanelType::class, [
    'authorized_blocks' => [MyBlock::class]
]);

$builder->add('content', PanelType::class, [
    'unauthorized_blocks' => [MyBlock::class]
]);

阅读更多 以了解与 EasyAdmin 4 的集成以及在您的 CRUDController 中定义 PanelField

创建一个块实体及其块管理器

首先创建您的 Block 实体,它应扩展包的 Block 实体,如下例所示

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Umanit\BlockBundle\Entity\Block;

/**
 * @ORM\Entity()
 */
 #[ORM\Entity]
class TitleAndText extends Block
{
    /**
     * @var string
     *
     * @ORM\Column(name="title", type="string")
     */
    #[ORM\Column(name: 'title', type: 'string')]
    private $title;

    /**
     * @var string
     *
     * @ORM\Column(name="text", type="text")
     */
    #[ORM\Column(name: 'text', type: 'text')]
    private $text;
    
    // getters and setters ...
    
    /**
     * 
     */
    public function __toString()
    {
        return $this->getTitle() ? : 'New TitleAndText';
    }
}

然后,创建一个 块管理器 服务及其 表单类型,该类型应扩展 AbstractBlockType。此服务将定义用于管理您的 的表单。它还将允许您定义前端中 的渲染。

<?php

namespace AppBundle\BlockManager;

use AppBundle\Entity\TitleAndText;
use AppBundle\Form\TitleAndTextType;
use Umanit\BlockBundle\Block\AbstractBlockManager;
use Umanit\BlockBundle\Model\BlockInterface;
use Twig\Environment;
use \Twig\Error\LoaderError;
use \Twig\Error\RuntimeError;
use \Twig\Error\SyntaxError;

class TitleAndTextManager extends AbstractBlockManager
{
    /** @var Environment */
    private $twig;

    /**
     * QuoteBlockManager constructor.
     *
     * @param Environment $twig
     */
    public function __construct(Environment $twig)
    {
        $this->twig = $twig;
    }

    /**
     * Define which Block type is managed by this Manager
     *
     * @return string
     */
    public function getManagedBlockType(): string
    {
        return TitleAndText::class;
    }

    /**
     * This method must return the form typemanaged by this block manager.
     *
     * @return string
     */
    public function getManagedFormType(): string
    {
        return TitleAndTextType::class;
    }

    /**
     * Define how the block should be rendered on the front end.
     *
     * @param BlockInterface $block
     * @param array          $parameters
     *
     * @return string
     * @throws LoaderError
     * @throws RuntimeError
     * @throws SyntaxError
     */
    public function render(BlockInterface $block, array $parameters = []): string
    {
        return $this->twig->render('blocks/title-and-text.html.twig', ['block' => $block]);
    }
}
<?php

namespace AppBundle\Form\TitleAndTextType;

use Umanit\BlockBundle\Form\AbstractBlockType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\NotBlank;

class TitleAndTextType extends AbstractBlockType
{
    /**
     * Define the form used by the back end to administrate the block.
     *
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('title', TextType::class, [
                'constraints' => [
                    new NotBlank(),
                ],
            ])
            ->add('text', TextareaType::class, [
                'constraints' => [
                    new NotBlank(),
                ],
            ])
        ;
    }
}

最后,使用 umanit_block.manager 标记您的 块管理器

# config/services.yml
services:
    app.block_manager.title_and_text_manager:
        class: AppBundle\BlockManager\TitleAndTextManager
        arguments: ['@twig']
        tags: ['umanit_block.manager']

渲染您的块

使用 twig 函数 umanit_block_render 来渲染您每个块。

{# page.html.twig #}

{% for block in page.content.blocks %}
    {{ umanit_block_render(block) }}
{% endfor %}

umanit_block_render 将找到正确的 BlockManager 并调用其 render 方法。

您可以将参数数组传递给 umanit_block_render。这些参数将被传递到 BlockManagerrender 方法。

在集合项中嵌入面板

块包使用 Stimulus,因此您不需要在您的端上做任何事情:控制器将在它们添加到 DOM 中时实例化。

与 UmanitTranslationBundle 的集成

此包与 UmanitTranslationBundle 完全兼容。一旦翻译一个 面板,所有 实例及其属性也将被翻译。如果您的 BlockManager 表单(例如,用于筛选 EntityType)需要地区参数,请将参数按如下方式传递给 PanelType

$builder->add('content', PanelType::class, ['locale' => 'be']);

与 EasyAdmin 4 的集成

注册提供的表单主题

在您的 DashboardController

class DashboardController extends AbstractDashboardController
{
    public function configureCrud(): Crud
    {
        return Crud::new()
                   // ...
                   ->setFormThemes([
                       // ...
                       '@UmanitBlock/easy_admin/form/panel.html.twig'
                   ])
        ;
    }
}

使用 PanelField

如果您正在定义 CrudController,则可以使用提供的 PanelField

public function configureFields(string $pageName): iterable
{
    yield PanelField::new('content');
}

PanelType 一样,如果需要将可用的块列表限制为一些选择选项,则可以定义 authorized_blocksunauthorized_blocks

                    ->setFormTypeOption('authorized_blocks', [MyBlock::class])
                    // or
                    ->setFormTypeOption('unauthorized_blocks', [MyBlock::class])

在块中使用 EasyAdmin 的表单类型

例如,您可能想在您的块中使用 FileUploadType。块包仅与 Symfony 表单类型一起使用,这意味着您将无法在这些字段中使用 EA 字段并利用它们强大的配置器。然而,您仍然可以在您的块表单类型中使用关联的表单类型,但您可能需要手动处理选项。

block.js Stimulus 控制器在块被添加到 DOM 后分派 ea.collection.item-added 事件,因此 EA JS 将绑定到它。

CKEditor

如果您想在块中使用它,请阅读专门的 CKEditor 文档。