jbtronics/settings-bundle

一个用于在 symfony 应用中轻松创建类型安全、用户可配置设置的 symfony 扩展包

安装量: 1,881

依赖项: 1

建议者: 0

安全: 0

星标: 75

关注者: 4

分支: 3

开放问题: 1

类型:symfony-bundle

v2.4.1 2024-08-06 22:36 UTC

This package is auto-updated.

Last update: 2024-09-06 22:50:22 UTC


README

文档

codecov

设置包

设置包是一个 symfony 扩展包,让您能够轻松创建和管理用户可配置的设置,这些设置可以通过 Web 前端进行更改。它允许您轻松创建类型安全的设置对象,这些对象可以通过 Web 前端轻松管理和更改您的 symfony 应用程序。

简介

默认情况下,symfony 主要通过配置文件中的参数进行配置,需要重新编译容器,或者通过环境变量进行配置,这些变量不能由应用程序本身轻松更改。

然而,您通常希望管理员和用户能够更改应用程序的设置和配置。此扩展包提供了一个简单的实现方式。与其他具有类似目标的扩展包不同,此扩展包试图尽可能模块化和类型安全。因此,您将设置定义为类,并在您的应用程序中访问此类对象,而不是执行简单的键值查找,返回类型混合。

所有相关的设置定义都直接在设置类中通过元数据属性完成。这使得理解和管理设置变得容易。此扩展包还提供了一个简单的方式来生成更改设置的表单,可以轻松集成到您的应用程序中。

功能

  • 基于类的设置,该设置可由扩展包轻松管理
  • 对设置的类型安全访问
  • 易于使用的 API
  • 在服务构造函数中通过依赖注入检索设置
  • 在许多情况下几乎不需要配置,因为扩展包试图尽可能从代码元数据(如属性类型等)中提取信息。
  • 支持各种存储后端,如数据库、JSON 文件、PHP 文件等。(可以轻松实现自定义后端)
  • 使用 symfony/validator 来轻松限制设置参数的可能值
  • 自动生成更改设置的表单
  • 轻松实现设置版本控制和自动将旧存储数据迁移到当前格式
  • 可以懒加载设置,这样只需加载真正需要的设置
  • 集成分析器以轻松调试
  • 可以使用环境变量轻松配置自动化部署

要求

  • PHP 8.1 或更高版本
  • Symfony 6.4 或更高版本(与 Symfony 7.0 兼容)
  • 如果应生成表单或使用验证,则需要 symfony/forms 和 Symfony/validator
  • 如果您想使用 twig 扩展在模板中访问设置,则需要 twig
  • 如果您想使用 doctrine 存储适配器,则需要 doctrine/orm 和 doctrine-bundle

安装

通过 composer 将扩展包添加到您的 symfony 项目中

composer require jbtronics/settings-bundle

如果您正在使用 symfony flex,则扩展包应自动启用。否则,您必须将扩展包添加到您的 config/bundles.php 文件中

return [
    // ...
    Jbtronics\SettingsBundle\JbtronicsSettingsBundle::class => ['all' => true],
];

用法

以下部分仅提供一个快速概述。有关完整信息,请参阅 文档

设置类是简单的PHP类,它们通过#[Settings]属性进行了注解。它们必须位于配置为存储设置类的路径中(通常是src/Settings),在您的symfony项目中。该组件将自动查找并注册此目录中所有设置类。

类的属性用于存储不同的数据。类似于doctrine中的#[ORM\Column]属性,您可以使用#[SettingsParameter]属性将类属性转换为可管理的参数。属性可以是公共的、受保护的或私有的(因为SettingsBundle通过反射访问它们),但您有某种方式来访问属性以获取/设置软件中的配置参数。您必须配置用于将归一化数据从存储后端映射到属性类型的类型映射器。该组件自带一些默认类型映射器,但您也可以实现自己的类型映射器。

<?php
// src/Settings/TestSettings.php

namespace App\Settings;

use Jbtronics\SettingsBundle\Settings\Settings;
use Jbtronics\SettingsBundle\Settings\SettingsParameter;
use Jbtronics\SettingsBundle\ParameterTypes\StringType;
use Jbtronics\SettingsBundle\ParameterTypes\IntType;
use Jbtronics\SettingsBundle\Storage\JSONFileStorageAdapter;
use Jbtronics\SettingsBundle\Settings\SettingsTrait;
use Symfony\Component\Validator\Constraints as Assert;


// The settings attribute makes a simple class to settings
// You can configure the storage backend (here JSON files) to use either here or globally in the bundle configuration
#[Settings(storageAdapter: JSONFileStorageAdapter::class)]
class TestSettings {
    use SettingsTrait; // Disable constructor and __clone methods

     //The properties are public here for simplicity, but it can also be protected or private

    //In many cases this attribute with zero config is enough, the type mapper is then derived from the declared type of the property
    #[SettingsParameter()]
    public string $myString = 'default value'; // The default value can be set right here in most cases

    //Or you can explicitly set the type mapper and some options
    #[SettingsParameter(type: IntType::class, label: 'My Integer', description: 'This value is shown as help in forms.')] 
    #[Assert\Range(min: 5, max: 10,)] // You can use symfony/validator to restrict possible values
    public ?int $myInt = null;
}

与设置交互的主要方式是使用SettingsManagerInterface服务。它提供了一个get()方法,允许检索给定设置类的当前设置。如果没有加载,则管理器将从存储后端加载所需的设置(或使用默认值初始化一个新实例)。实例被缓存,因此管理器将始终为给定的设置类返回相同的实例。管理器还提供了一个save()方法,允许将当前设置保存到存储后端并持久化更改。

use Jbtronics\SettingsBundle\Settings\SettingsManagerInterface;

class ExampleService {
    public function __construct(private SettingsManagerInterface $settingsManager) {}

    public function accessAndSaveSettings(): void
    {
        /** @var TestSettings $settings This is an instance of our previously defined setting class, containing the stored settings */
        $settings = $this->settingsManager->get(TestSettings::class);

        //To read the current settings value, just access the property
        dump('My string is: ' . $settings->myString);

        //To change the settings, just change the property (or call the setter)
        $settings->myString = 'new value';

        //And save the settings to the storage backend
        $this->settingsManager->save($settings);


        //You can also access the settings via a given name (which is the part before the "Settings" suffix of the class name in lowercase, by default)
        $settings = $this->settingsManager->get('test');

        //You can set an invalid value to the parameters
        $settings->myInt = 42;

        //But the bundle will throw an exception, when you try to save the settings
        $this->settingsManager->save($settings); // Throws an excpetion
    }
}

如果您有一个依赖于设置的服务的组件,您可以直接通过依赖注入注入当前设置实例。该组件为每个设置类注册了一个服务,可以像其他任何服务一样注入到您的服务中。在内部,设置管理器的get()方法被调用来检索一个延迟加载的设置实例。

class ExampleService {
    public function __construct(private TestSettings $settings) {
        //This is equivalent to calling $settings = $settingsManager->get(TestSettings::class, lazy: true)
        //The settings are lazy, meaning that they are only loaded from storage, when you access a property
        if ($this->settings->myString === 'some value') {
            //Do something
        }
    }
}

通过依赖注入注入的实例与您通过设置管理器获得的实例相同。这意味着,所有对设置实例的更改将自动更新到您应用程序的所有部分。

表单

该组件可以自动生成用于更改设置类的表单。这是通过SettingsFormFactoryInterface完成的,该接口创建了一个包含编辑一个或多个设置类字段的表单构建器。您也可以仅渲染设置的一个子集。验证属性将被检查并映射到表单错误。这样,您可以轻松创建一个控制器,让用户更改设置。

<?php

class SettingsFormController {

    public function __construct(
        private SettingsManagerInterface $settingsManager,
        private SettingsFormFactoryInterface $settingsFormFactory,
        ) {}

    #[Route('/settings', name: 'settings')]
    public function settingsForm(Request $request): Response
    {
        //Create a temporary copy of the settings object, which we can modify in the form without breaking anything with invalid data
        $settings = $this->settingsManager->createTemporaryCopy(TestSettings::class);

        //Create a builder for the settings form
        $builder = $this->settingsFormFactory->createSettingsFormBuilder($settings);

        //Add a submit button, so we can save the form
        $builder->add('submit', SubmitType::class);

        //Create the form
        $form = $builder->getForm();

        //Handle the form submission
        $form->handleRequest($request);

        //If the form was submitted and the data is valid, then it
        if ($form->isSubmitted() && $form->isValid()) {
            //Merge the valid data back into the managed instance
            $this->settingsManager->mergeTemporaryCopy($settings);

            //Save the settings to storage
            $this->settingsManager->save();
        }

        //Render the form
        return $this->render('settings.html.twig', [
            'form' => $form->createView(),
        ]);
    }
}

表单渲染可以通过参数属性进行自定义。有关完整信息,请参阅文档

Twig模板

在twig模板中,您可以通过settings_instance()函数访问设置,该函数的行为类似于SettingsManagerInterface::get()函数,并返回当前设置实例。

{# @var settings \App\Settings\TestSettings #}
{% set settings = settings_instance('test') %}
{{ dump(settings) }}

{# or directly #}
{{ settings_instance('test').myString }}

许可证

SettingsBundle是在MIT许可证下授权的。这基本上意味着只要您保留版权/许可证信息,您就可以为任何目的使用此组件(甚至可以商业使用)。

有关更多信息,请参阅LICENSE