asgard/form

v0.3.1 2016-05-13 11:31 UTC

This package is not auto-updated.

Last update: 2024-09-14 15:58:04 UTC


README

#表单

Build Status

表单库使得构建表单、渲染它们、在提交后记住输入以及自动处理、验证并防止CSRF攻击变得非常容易。

##安装 如果你正在开发Asgard项目,你不需要安装这个库,因为它已经是标准库的一部分。

composer require asgard/form 0.*

##Asgard框架中的使用

使用表单服务的优点是它会为表单提供所有必要的依赖

$container->make('form', [
	'name', #name (optional)
	[ #params (optional)
		'action'  => 'form.php',
		'enctype' => 'multipart/form-data',
		'attrs'   => [
			'class' => 'formClass'
		]
	],
	\Asgard\Http\Request::CreateFromGlobals(), #request (optional, Asgard will feed the form with the current request)
	[ #fields (optional)
		'name'    => new TextField(),
		'content' => new TextField(),
	]
]);

在控制器(或任何使用视图容器的类)中,可以通过 $this->getContainer() 获取 $container。您也可以通过 \Asgard\Container\Container::singleton() 访问它。

##框架外的使用

在这里,您必须自己提供依赖(请参阅下一节)

$form = new \Asgard\Form\Form(
	'name', #name (optional)
	[ #params (optional)
		'action'  => 'form.php',
		'enctype' => 'multipart/form-data',
		'attrs'   => [
			'class' => 'formClass'
		]
	],
	\Asgard\Http\Request::CreateFromGlobals(), #request (optional)
	[ #fields (optional)
		'name'    => new TextField(),
		'content' => new TextField(),
	]
);

如果没有提供enctype,当表单包含文件时,它将自动使用 "multipart/form-data"

##表单依赖

###请求

$form->setRequest(\Asgard\Http\Request::createFromGlobals());

###翻译器

$form->setTranslator(new \Symfony\Component\Translation\Translator('en'));

##表单选项

访问或修改表单参数

$param = $form->getOption('action');
$form->setOption('action', $action);

一些常见的参数包括

  • action(例如,/url/to/page)
  • enctype(例如,multipart/form-data)

##表单HTTP方法

默认情况下,表单从POST请求获取输入,但如果您想创建一个只使用GET输入的表单

$form->setMethod('get');

##字段

字段是表单的单个输入。所有字段都扩展了 \Asgard\Form\Field 类。 以下是当前所有可用字段的列表

###验证

要为字段添加特定的验证规则,请使用 'validation' 选项

$form['field'] = new \Asgard\Form\Field\TextField(['validation'=>[
	'minlength' => 5,
	'maxlength' => 5,
]]);

检查输入是否有效

$form->isValid(); #returns true|false

获取错误

$errors = $form->errors();

获取字段或组错误

$errors = $form['title']->errors();

获取仅通用错误或不属于特定字段的错误

$errors = $form->getGeneralErrors();

验证组

$form['field'] = new \Asgard\Form\Field\TextField(['validation'=>[
	'minlength' => [
		5,
		'groups' => ['registration']
	]
]]);

使用少于5个字符的文本

$form->isValid(['registration']); #false
$form->isValid(); #true

验证在验证文档中有进一步解释。

###字段默认值

要为字段设置默认值,请使用 'default' 选项

$form['field'] = new \Asgard\Form\Field\TextField(['default'=>'placeholder']);

###渲染字段

字段使用小部件进行渲染。每种类型的字段都使用默认小部件,但有时您可以使用不同的一个。有关渲染字段的多种方式,请参阅以下字段列表。

要使用默认小部件渲染字段,请使用以下方法

echo $form['field']->def();

###小部件

小部件通过短名称(如 "text"、"password"、"select" 等)标识,并在渲染字段时调用,例如

echo $form['field']->text();

"text" 是我们想要用于渲染字段的 Widget 名称。

默认情况下,表单将在 \Asgard\Form\Widget 中查找对应的控件。但是,您也可以管理可用的控件

###字段标签

显示字段的标签

echo $form['field']->label();

或整个标签标签

echo $form['field']->labelTag();

###字段列表

布尔值

$form['field'] = new \Asgard\Form\Field\BooleanField;

显示复选框。

国家

$form['field'] = new \Asgard\Form\Field\BooleanField;

显示包含所有国家的选择字段。

csrf

$form['field'] = new \Asgard\Form\Field\CSRFField;

向表单添加隐藏字段以防止CSRF攻击。

日期

$form['field'] = new \Asgard\Form\Field\DateField;

渲染三个选择字段(日/月/年)

$form['field']->def();
#or
$form['field']->date();

渲染文本字段

$form['field']->text();

日期时间

$form['field'] = new \Asgard\Form\Field\DatetimeField;

渲染六个选择字段(秒/分/时/日/月/年)

$form['field']->def();
#or
$form['field']->datetime();

渲染文本字段

$form['field']->text();

时间

$form['field'] = new \Asgard\Form\Field\TimeField;

渲染三个选择字段(秒/分/时)

$form['field']->def();
#or
$form['field']->time();

渲染文本字段

$form['field']->text();

$form['field'] = new \Asgard\Form\Field\DayField;

添加一个单选字段,包含从1到31天的选项。

文件

$form['field'] = new \Asgard\Form\Field\FileField;

添加一个文件字段。

隐藏

$form['field'] = new \Asgard\Form\Field\HiddenField;

向表单添加一个隐藏字段。

$form['field'] = new \Asgard\Form\Field\MonthField;

添加一个单选字段,包含从1到12个月的选项。

多选

$form['field'] = new \Asgard\Form\Field\SelectField(['choices'=>['bob', 'joe', 'david']);

渲染多选

$form['field']->def();
#or
$form['field']->multipleselect();

渲染复选框

$form['field']->checkboxes();
#or
foreach($form['field']->getCheckboxes() as $checkbox)
	echo $checkbox->label().': '.$checkbox;

选择

$form['field'] = new \Asgard\Form\Field\SelectField(['choices'=>['bob', 'joe', 'david']);

添加一个单选字段。

文本

$form['field'] = new \Asgard\Form\Field\TextField;

$form['field'] = new \Asgard\Form\Field\YearField;

添加一个单选字段,包含过去50年的选项。

##组和表单 组是一组字段。例如,您可能有一个用于运货地址字段的组,另一个用于账单地址字段的组。您还可以有包含其他组的组。表单本身是一个包含组和字段的组。

要了解组或表单有多少字段或子组

$count = $group->size();

表单和组就像数组一样构建。要添加字段

$form['title'] = new \Asgard\Form\Field\TextField;

要获取表单提交后的值

$value = $form['title']->value();

您可以将整个组添加到表单中

$form['address'] = [
	'number' => new Field\TextField,
	'street' => new Field\TextField,
	'city' => new Field\TextField,
	'zipcode' => new Field\TextField
];

在表单中,数组将转换为 \Asgard\Form\Group 对象。您可以通过像表单一样访问组字段

$value = $form['address']['street']->value();

因为表单也是一个组,所以您也可以嵌入表单

$personForm = new \Asgard\Form\Form;
$personForm['firstname'] = new Field\TextField;
$personForm['lastname'] = new Field\TextField;

$form['person'] = $personForm;

并且像这样访问字段

$form['person']['firstname']->value();

您还可以遍历组或表单字段

foreach($group as $field) {
	// do something with the field
}

##动态组

###用法 动态组在您在一个组中有不确定数量的字段时非常有用。例如,一个用户可以添加任意多的名字,每个名字对应一个字段的表单。

要添加动态组,使用

$callback = function($data) {
	return new \Asgard\Http\Field\TextField;
};
$form['names'] = \Asgard\Form\DynamicGroup($callback);

这将自动为组 "names" 中的每个输入创建一个 TextField。如果用户发送5个名字,表单将适应并创建5个 TextField 来包含这5个名字。

###预填充 您甚至可以预填充动态组

$form['names'][] =  new \Asgard\Http\Field\TextField(['default'=>'name1']);
$form['names'][] =  new \Asgard\Http\Field\TextField(['default'=>'name2']);

###渲染

echo $form->open();
foreach($form['names'] as $field)
	echo $field->def();
echo $form->submit();
echo $form->close();

您可以为动态组的字段设置匿名函数以进行渲染

$form['names']->setDefaultRender(function($field) {
	return $field->label().': '.$field->def();
});

然后在视图中使用以下代码

echo $form->open();
foreach($form['names'] as $field)
	echo $form['names']->def($field);
echo $form->submit();
echo $form->close();

###使用jQuery在前端处理多个字段

要允许用户自行添加字段,使用以下代码片段

<script>
function add() {
	var newfield = $('<?php echo $form['names']->renderTemplate("'+$('.name').length+'") ?>');
	$('#slides').append(newfield);
}
</script>

echo $form->open();
echo '<div id="names">';
foreach($form['names'] as $field)
	echo '<div>'.$field->label().': '.$field-def(['attrs'=>['class'=>'name']]).'</div>';
echo '</div>';

<input type="button" name="add" value="Add a name" onclick="add()">
echo $form->submit();
echo $form->close();

方法 renderTemplate 在用户点击 "添加" 按钮时生成创建新HTML字段的javascript模板。

##保存

检查表单是否已发送

$form->sent(); #returns true|false

保存表单

$form->save($validationGroups=[]);

验证组在上面的 "验证组" 中解释。

如果发生错误,将引发异常

try {
	$form->save();
} catch(\Asgard\Form\FormException $e) {
	//...
}

如果输入有效,它将执行表单的 doSave() 方法,默认情况下不执行任何操作。它还会尝试保存每个嵌套表单。

但是,您可以创建扩展表单类并重写 "doSave" 方法或使用回调的自定义类

$form->setPreSaveCallback(function($form) {
	// do something before validation
});
$form->setSaveCallback(function($form) {
	// do something to save the form
});
$form->save()

##CSRF保护

要启用表单的CSRF保护

$form->csrf();

禁用它

$form->csrf(false);

如果没有 CSRF 令牌,表单将无效。错误信息可以通过 $form->getGeneralErrors() 或 $form['_csrf_token']->error() 获取。

##表单数据

从已发送的表单中获取数据

$data = $form->data();

重置数据

$form->reset();

手动设置数据

$form->setData(['title' => 'abc']); 

##渲染表单

echo $form->open($params=[]); #prints the opening tag. Params will override the parameters passed to the form instancefd

//render fields e.g. $form['title']->def();

echo form->submit('Send'); #prints a simple submit button with text "Send"
echo $form->close(); #prints the closing tag and an hidden input for csrf if enabled

##管理小部件

###实例

在 Asgard 框架中,你可以使用服务

$wm = $container['widgetManager'];

否则,你也可以通过以下方式访问表单小部件管理器

$wm = $form->getWidgetManager();

###注册小部件

$wm->setWidget('text', 'MyClasses\Widget\TextWidget');

###注册命名空间

$wm->addNamespace('MyClasses\Widgets');

当使用未知的小部件时,小部件管理器将尝试在所有已注册的命名空间中查找小部件。如果存在类 MyClasses\Widget\TextWidget,它将被用来渲染字段。

###注册小部件工厂

这对于依赖注入非常有用。

$wf = new WidgetFactory($dep);
$wm->setWidgetFactory('text', $wf);

小部件工厂必须实现 \Asgard\Form\WidgetFactoryInterface,该接口有一个方法

public function create($name, $value, $options, $form);

此方法必须构建并返回一个 Widget 对象。

###示例

$form = $container->make('form');
#or
$form = new \Asgard\Form\Form;
$form->getWidgetManager()->setWidget('text', 'MyClasses\Widget\TextWidget');
$form['title'] = new \Asgard\Field\TextField;
echo $form['title']->text();

##示例

###用户注册

构建表单

$form = $container->make('form', ['user']);
#or
$form = new \Asgard\Form\Form('user');

$form['username'] = new \Asgard\Form\Field\TextField(['validation'=>'required']);
$form['password'] = new \Asgard\Form\Field\TextField(['validation'=>'required', 'widget' => 'password']);

if($form->sent()) {
	if($form->isValid()) {
		$username = $form['username']->value();
		$password = $form['password']->value();
		// save in database..
		echo 'Good :)';
	}
	else {
		echo 'Bad :(';
		foreach($form->errors() as $error)
			echo "\n".$error;
	}
}

显示表单

echo $form->open();
echo $form['username']->def();
echo $form['password']->password();
echo $form->close();

//todo widgetfactory

###贡献

请将所有问题和拉取请求提交到 asgardphp/asgard 仓库。

许可证

Asgard 框架是开源软件,许可协议为 MIT 许可证