b2pweb/bdf-form-attribute

使用 PHP 8 属性和类型化属性声明表单,基于 bdf-form

dev-master / 1.0.x-dev 2024-03-04 11:16 UTC

This package is auto-updated.

Last update: 2024-09-26 10:04:29 UTC


README

build Scrutinizer Code Quality Code Coverage Packagist Version Total Downloads Type Coverage

使用 PHP 8 属性和类型化属性声明表单,基于 BDF 表单

用法

使用 composer 安装

composer require b2pweb/bdf-form-attribute

声明表单类

要使用 PHP 8 属性创建表单,首先必须扩展 AttributeForm

然后声明所有输入元素和按钮作为属性

  • 对于元素:public|protected|private MyElementType $myElementName;
  • 对于按钮:public|protected|private ButtonInterface $myButton;

最后,在属性(或表单类)上使用属性来配置元素,添加约束,转换...

#[Positive, UnitTransformer, GetSet]
public IntegerElement $weight;

BDF 表单示例的改编:处理实体

use Bdf\Form\Attribute\Form\Generates;
use Bdf\Form\Leaf\StringElement;
use Symfony\Component\Validator\Constraints\NotBlank;
use Bdf\Form\Attribute\Child\GetSet;
use Bdf\Form\Attribute\AttributeForm;
use Bdf\Form\Leaf\Date\DateTimeElement;
use Bdf\Form\Attribute\Element\Date\ImmutableDateTime;
use Bdf\Form\Attribute\Child\CallbackModelTransformer;
use Bdf\Form\ElementInterface;

// Declare the entity
class Person
{
    public string $firstName;
    public string $lastName;
    public ?DateTimeInterface $birthDate;
    public ?Country $country;
}

#[Generates(Person::class)] // Define that PersonForm::value() should return a Person instance
class PersonForm extends AttributeForm // The form must extend AttributeForm to use PHP 8 attributes syntax
{
    // Declare a property for declare an input on the form
    // The property type is used as element type
    // use NotBlank for mark the input as required
    // GetSet will define entity accessor
    #[NotBlank, GetSet] 
    private StringElement $firstName;

    #[NotBlank, GetSet] 
    private StringElement $lastName;

    // Use ImmutableDateTime to change the value of birthDate to DateTimeImmutable
    #[ImmutableDateTime, GetSet]
    private DateTimeElement $birthDate;

    // Custom transformer can be declared with a method name as first parameter of ModelTransformer
    // Transformers methods must be declared as public on the form class
    #[ImmutableDateTime, CallbackModelTransformer(toEntity: 'findCountry', toInput: 'extractCountryCode'), GetSet]
    private StringElement $country;
    
    // Transformer used when extracting input value from entity
    public function findCountry(Country $value, ElementInterface $element): string
    {
        return $value->code;
    }
    
    // Transformer used when filling entity with input value
    public function extractCountryCode(string $value, ElementInterface $element): ?Country
    {
        return Country::findByCode($value);
    }
}

支持的属性

此库支持各种属性类型来配置表单元素

从属性生成配置器代码

为了提高性能,并避免使用反射,可以使用属性来生成配置器的 PHP 代码,而不是动态配置表单。

为此,将 CompileAttributesProcessor 作为表单构造函数的参数使用。

const GENERATED_NAMESPACE = 'Generated\\';
const GENERATED_DIRECTORY = __DIR__ . '/var/generated/form/';

// Configure the processor by setting class and file resolvers
$processor = new CompileAttributesProcessor(
    fn (AttributeForm $form) => GENERATED_NAMESPACE . get_class($form) . 'Configurator', // Retrieve the configurator class name from the form object
    fn (string $className) => GENERATED_DIRECTORY . str_replace('\\', DIRECTORY_SEPARATOR, $className) . '.php', // Get the filename of the configurator class from the configurator class name
);

$form = new MyForm(processor: $processor); // Set the processor on the constructor
$form->submit(['firstName' => 'John']); // Directly use the form : the configurator will be automatically generated

// You can also pre-generate the form configurator using CompileAttributesProcessor::generate()
$processor->generate(new MyOtherForm());

可用的属性

在表单类上

在按钮属性上

在元素属性上