droath / console-form
Symfony 控制台表单助手。
Requires
- php: >=5.4
- symfony/console: ^2.8 || ^3.0
- symfony/finder: ^2.8 || ^3.0 || ^4.0
Requires (Dev)
- phpunit/phpunit: ^5.5
- squizlabs/php_codesniffer: ^2.8
README
当使用 Symfony 控制台组件时,这是一个简单的表单解决方案。
创建表单有两种方式,一种是使用独立方法,这通常发生在命令 execute 方法中。
或者利用自动发现功能,这样你可以在整个项目中重用表单,这保持了表单逻辑与执行的命令解耦。
入门指南
首先,您需要使用 composer 下载控制台表单库
composer require droath/console-form
将 \Droath\ConsoleForm\FormHelper 设置为控制台应用程序 HelperSet 中的辅助类
<?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();