magdev / console-form
Symfony 控制台表单助手。
Requires
- php: >=5.4
- symfony/console: ^2.8 || ^3.0
- symfony/finder: ^2.8 || ^3.0
Requires (Dev)
- phpunit/phpunit: ^5.5
- squizlabs/php_codesniffer: ^2.8
README
使用 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();