magdev/console-form

Symfony 控制台表单助手。

0.0.7 2017-10-15 19:03 UTC

This package is auto-updated.

Last update: 2024-09-05 08:58:47 UTC


README

Build Status

使用 Symfony 控制台组件时,这是一个简单的表单解决方案。

表单可以有两种创建方式,一种是通过独立方法创建,通常发生在命令 execute 方法中。

或者利用自动发现特性,这样你可以在整个项目中重用表单,从而将表单逻辑与执行命令解耦。

入门指南

首先,您需要使用 composer 下载控制台表单库

composer require droath/console-form

在控制台应用程序的 HelperSet 中设置 \Droath\ConsoleForm\FormHelper 为助手类

<?php

$application = new \Symfony\Component\Console\Application('Project-Demo', '0.0.1');

$application->getHelperSet()
    ->set(new \Droath\ConsoleForm\FormHelper());
...

自动发现

如果您决定使用自动发现功能,则需要使用 \Droath\ConsoleForm\FormDiscovery

<?php
...

$formDiscovery = (new \Droath\ConsoleForm\FormDiscovery())
    ->discover(__DIR__ . '/Form', '\Droath\Project\Form');

$application->getHelperSet()
    ->set(new \Droath\ConsoleForm\FormHelper($formDiscovery));
...

\Droath\ConsoleForm\FormDiscovery::discover() 方法接受两个参数,第一个参数是一个目录或目录数组。这些目录会搜索实现了 \Droath\ConsoleForm\FormInterface 接口的表单类。第二个参数是类命名空间。

以下是一个表单类需要实现的示例,以便自动发现功能能够找到它

<?php

namespace Droath\Project\Form;

use Droath\ConsoleForm\Field\BooleanField;
use Droath\ConsoleForm\Field\SelectField;
use Droath\ConsoleForm\Field\TextField;
use Droath\ConsoleForm\Form;
use Droath\ConsoleForm\FormInterface;

/**
 * Define project setup form.
 */
class ProjectSetup implements FormInterface
{
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'project.form.setup';
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm()
    {
        return (new Form())
            ->addField(new TextField('name', 'What is your name?'))
            ->addField((new SelectField('gender', 'What is your gender?'))
                ->setOptions(['male', 'female', 'other']))
            ->addField(new BooleanField('send_newletter', 'Email me the weekly newsletter'));
    }
}

表单基础

在命令类中与表单助手交互。您可以使用独立方法创建表单,或者通过定义的名称检索表单(自动发现需要实现)。

首先,我将向您展示独立方法,您可以创建一个表单

<?php

namespace Droath\Project\Command;

use Droath\ConsoleForm\Field\BooleanField;
use Droath\ConsoleForm\Field\SelectField;
use Droath\ConsoleForm\Field\TextField;
use Droath\ConsoleForm\Form;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class Initialize extends Command
{
    /**
     * {@inheritdoc}
     */
    public function configure()
    {
        $this
            ->setName('init')
            ->setDescription('Initialize project config.');
    }

    /**
     * {@inheritdoc}
     */
    public function execute(InputInterface $input, OutputInterface $output)
    {
        $form = $this->getHelper('form')
            ->getForm($input, $output);

        $form->addFields([
            (new TextField('project', 'Project name'))
                ->setDefault('Demo Project'),
            (new SelectField('version', 'Project Version'))
                ->setOptions(['7.x', '8.x'])
                ->setDefault('8.x'),
        ]);

        $results = $form
            ->process()
            ->getResults();

        var_dump($results)
    }
    ...

如果使用 自动发现,您可以简单地通过名称检索表单

<?php

namespace Droath\Project\Command;

use Droath\ConsoleForm\Field\BooleanField;
use Droath\ConsoleForm\Field\SelectField;
use Droath\ConsoleForm\Field\TextField;
use Droath\ConsoleForm\Form;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class Initialize extends Command
{
    /**
     * {@inheritdoc}
     */
    public function configure()
    {
        $this
            ->setName('init')
            ->setDescription('Initialize project config.');
    }

    /**
     * {@inheritdoc}
     */
    public function execute(InputInterface $input, OutputInterface $output)
    {
        $form = $this->getHelper('form')
            ->getFormByName('project.form.setup', $input, $output);

        $results = $form
            ->process()
            ->getResults();

        var_dump($results)
    }

    ...

表单保存

很多时候,表单需要将结果保存到文件系统。表单的 save() 方法会显示一个确认消息,提示用户保存结果(这是可配置的)。如果输入为 true,则调用 save 可调用;否则忽略。

<?php

...
    $form
        ->addFields([
            (new TextField('project', 'Project name'))
                ->setDefault('Demo Project'),
            (new SelectField('version', 'Project Version'))
                ->setOptions(['7.x', '8.x'])
                ->setDefault('8.x'),
        ])
        ->save(function($results) {
            // Save results to filesystem or remote source.
            // Don't need to call process() as it's done inside the save method.
        });

表单字段组

有时您可能需要将字段分组。一个优点是能够收集一组字段的多个输入。正如下面的示例所示,setLoopUntil() 提供了最后给定的结果数组,这些值可以帮助确定是否应该停止收集数据。返回 false 来停止字段组迭代,否则设置为 true

<?php
...

    $form->addFields([
        (new TextField('name', 'Project Name')),
        (new FieldGroup('environments'))
            ->addFields([
                (new TextField('ssh_label', 'SSH Label'))
                    ->setRequired(false),
                (new TextField('ssh_host', 'SSH Host'))
                    ->setRequired(false),
                (new Textfield('ssh_uri', 'SSH URI'))
                    ->setRequired(false)
            ])
            ->setLoopUntil(function($result) {
                if (!isset($result['ssh_label'])) {
                    return false;
                }
                return true;
            })
    ]);

    $results = $form
        ->process()
        ->getResults();

表单字段

有三个基本的字段类型,分别是

  • 文本
  • 选择
  • 布尔

所有字段类型都源于基本字段类,因此大多数字段具有类似的方法和功能。

以下是一些最有用的字段方法示例

条件

setCondition() 方法允许字段基于用户先前输入的值显示。如果需要满足给定字段的条件,则可以多次设置此方法。

<?php
...
    $form
        ->addFields([
            (new TextField('project', 'Project name'))
                ->setDefault('Demo Project'),
            (new SelectField('version', 'Project Version'))
                ->setOptions(['7.x', '8.x'])
                ->setDefault('8.x'),
            (new TextField('another_option', 'More options for 7.x version'))
                ->setCondition('version', '7.x'),
        ]);

    $results = $form
        ->process()
        ->getResults();

“更多选项 7.x 版本”文本字段仅在先前问题中选择 7.x 版本时显示。

字段回调

setFieldCallback() 方法需要一个单独的回调函数,可以是任何有效的 PHP 可调用。回调将在表单处理生命周期中调用。字段回调接收两个参数,第一个参数是字段实例。第二个是所有先前问题的结果数组。

现在,您可以根据先前问题的结果为给定字段实例设置额外的方法。正如下面的示例所示,选择选项基于从“项目名称”文本字段检索到的结果添加。

<?php
...

    $form
        ->addFields([
            (new TextField('name', 'Project Name')),
            (new SelectField('version', 'Project Version'))
                ->setFieldCallback(function ($field, $results) {
                    if ($results['name'] === 'My Project') {
                        $field->setOptions([
                            '7' => '7x',
                            '8' => '8x'
                        ]);
                    } else {
                        $field->setOptions([
                            '11' => '11x',
                            '12' => '12x'
                        ]);
                    }
                }),
        ]);

子表单

setSubform() 方法需要一个回调函数来设置,这个函数可以是一个匿名函数或任何有效的PHP可调用函数。子表单函数在原始表单处理生命周期中被调用。

子表单可调用函数接受两个参数,第一个参数是子表单实例,第二个是输入的值。可调用函数不需要返回任何数据。此外,原始表单处理会处理子表单。

<?php
...

    $form
        ->addFields([
            (new BooleanField('questions', 'Ask questions?'))
                ->setSubform(function ($subform, $value) {
                    if ($value === true) {
                        $subform->addFields([
                            (new TextField('how_old', 'How old are you?')),
                            (new TextField('location', 'Where do you live?')),
                        ]);
                    }
                }),
        ]);

        $results = $form
            ->process()
            ->getResults();