表单规范数据与视图数据——有什么区别?
Form Norm Data vs. View Data - what's the difference?
In any form, the three different types of data are:
Model data - This is the data in the format used in your application (e.g. an Issue object). If you call Form::getData() or Form::setData(), you're dealing with the "model" data.
Norm Data - This is a normalized version of your data and is commonly the same as your "model" data (though not in our example). It's not commonly used directly.
View Data - This is the format that's used to fill in the form fields themselves. It's also the format in which the user will submit the data. When you call Form::submit($data), the $data is in the "view" data format.
但是我不明白常模数据和视图数据的区别。常模数据的用例是什么?文档的下一段 "So why Use the Model Transformer?" 对我来说没有任何意义。
让我们以 DateTimeType 小部件为例。
模型数据是Datetime
标准数据是array
(in the documentation)
视图数据是 string
(例如输入文本)
我找到的最好的解释是在 Symfony 的表格 class 描述中:
<?php
...
namespace Symfony\Component\Form;
use ...
/**
* Form represents a form.
*
* To implement your own form fields, you need to have a thorough understanding
* of the data flow within a form. A form stores its data in three different
* representations:
*
* (1) the "model" format required by the form's object
* (2) the "normalized" format for internal processing
* (3) the "view" format used for display
*
* A date field, for example, may store a date as "Y-m-d" string (1) in the
* object. To facilitate processing in the field, this value is normalized
* to a DateTime object (2). In the HTML representation of your form, a
* localized string (3) is presented to and modified by the user.
*
* In most cases, format (1) and format (2) will be the same. For example,
* a checkbox field uses a Boolean value for both internal processing and
* storage in the object. In these cases you simply need to set a value
* transformer to convert between formats (2) and (3). You can do this by
* calling addViewTransformer().
*
* In some cases though it makes sense to make format (1) configurable. To
* demonstrate this, let's extend our above date field to store the value
* either as "Y-m-d" string or as timestamp. Internally we still want to
* use a DateTime object for processing. To convert the data from string/integer
* to DateTime you can set a normalization transformer by calling
* addNormTransformer(). The normalized data is then converted to the displayed
* data as described before.
*
* The conversions (1) -> (2) -> (3) use the transform methods of the transformers.
* The conversions (3) -> (2) -> (1) use the reverseTransform methods of the transformers.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Form implements \IteratorAggregate, FormInterface
{
...
}
编辑:这是来自 Sf 表单组件(合)作者的视频,他在其中解释了数据格式并给出了规范化格式使用的示例 -> https://youtu.be/Q80b9XeLUEA?t=7m6s
所以,基本上,每个表单都有三种不同格式的数据。前两个是:模型数据 - 您在域模型中使用的数据,以及视图数据 - 您通常在 HTML 中输出为字符串或在提交前输入表单字段的数据。
两个简单的示例是 TextType 和 NumberType。
TextType中,模型数据为字符串,视图数据为字符串。
在 NumberType 中,模型数据是浮点数 - 在您的应用程序中,您处理的是浮点数类型,而视图数据是本地化的字符串。
但是,另一方面,如果我们看一下 DateType,事情会有点复杂,因为模型数据可能是字符串 ('YYYY-MM-DD')、整数(unix 时间戳)、数组或 DateTime 对象。视图数据可以是本地化字符串或数组。
例如,如果你想写一个事件监听器,你不能确定你会得到什么数据格式:
class MyDateType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add...
->addEventListener(
FormEvents::FormEvents::SUBMIT,
array($this, 'onSubmit')
)
;
}
public function onSubmit(FormEvent $event)
{
// BUT WHAT FORMAT DO I GET???
$data = $event->getForm()->getData();
}
}
幸运的是,Sf表格还有第三种数据格式——归一化格式。该格式是静态的 - 您始终知道您将获得什么,它始终是相同的数据类型!
public function onSubmit(FormEvent $event)
{
// $data will be DateTime object!
$data = $event->getForm()->getNormData();
}
简短的解释/简化,当我开始学习 symfony 形式时,我曾经用来记住这些事情:
- 模型数据:Model/Entity/Whatever形式的数据。就是你的数据源数据格式
- Norm数据:Form字段表单中的数据。如果你有
CollectionType
,例如,你有一个数组,如果你有一个DateTimeType
,你有一个DateTime
等等
- 查看数据:查看表单中的数据。
基本上,如果您的格式 "consistent" 介于这些 "layers" 之间,您永远(*)不需要创建转换器。
只是为每种类型做一个例子:
型号 --> 标准
如果您有一个实体(模型数据)并且您的表单中有一个EntityType
字段(规范数据 ), 你不需要使用任何变压器
如果您有一个实体(模型数据)并且您有一个 TextType
字段来表示您的实体,您需要使用 ModelTransformer
作为你的格式不一致
规范 --> 视图
(*) 任何 DateType
或 DateTimeType
都有一个直接插入数据类型的转换器:用于从视图(用户)日期格式(时区)和规范(或模型)格式转换(时区)
正如您在此处看到的,转换不仅在非一致数据类型之间发生,而且在同一类型内发生。
你也可以检查this presentation
提醒一句,ViewData 可以变成 ModelData,反之亦然,这完全违背了此处提供的解释,您可能会感到困惑。它发生在几乎所有真实的单词案例中。
这取决于形式是否复合。复合表单就是有多个字段的表单,所以基本上都是。
参见:
line 634 send to ViewTransformer mix of view data (from main form) and model data (from children forms). Is it really expected?
是的 :) 原因我在上面已经解释过了。
继续:
简单表单=>查看数据==请求数据
复合形式=>查看数据==(data_class|数组)映射子模型数据,使用DataMapper。
来源:https://github.com/symfony/symfony/issues/22371#issuecomment-293494324
并且:
Internally the compound form uses its view data to map the data of the children.
我做了更多的研究:
As you say the compound option determines if PropertyPathMapper will be used. That's OK.
->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null)
Also as you say the Form class is using the mapper to map the view data to the forms. That's OK too.
$this->config->getDataMapper()->mapDataToForms($viewData, $iterator);
Then PropertyPathMapper mapper is setting the data on the forms. Hmm...
$form->setData($this->propertyAccessor->getValue($data, $propertyPath));
Why PropertyPathMapper trough Form is setting ViewData on forms that expect ModelData?
public function setData($modelData);
mapper中的ViewData是怎么变成ModelData的?为什么 ModelData 没有映射到表单上?为什么 data_class
适用于 ViewData 而不是 ModelData 更有意义?
来源:https://github.com/symfony/symfony/issues/20880#issuecomment-267129575
In any form, the three different types of data are:
Model data - This is the data in the format used in your application (e.g. an Issue object). If you call Form::getData() or Form::setData(), you're dealing with the "model" data.
Norm Data - This is a normalized version of your data and is commonly the same as your "model" data (though not in our example). It's not commonly used directly.
View Data - This is the format that's used to fill in the form fields themselves. It's also the format in which the user will submit the data. When you call Form::submit($data), the $data is in the "view" data format.
但是我不明白常模数据和视图数据的区别。常模数据的用例是什么?文档的下一段 "So why Use the Model Transformer?" 对我来说没有任何意义。
让我们以 DateTimeType 小部件为例。
模型数据是Datetime
标准数据是array
(in the documentation)
视图数据是 string
(例如输入文本)
我找到的最好的解释是在 Symfony 的表格 class 描述中:
<?php
...
namespace Symfony\Component\Form;
use ...
/**
* Form represents a form.
*
* To implement your own form fields, you need to have a thorough understanding
* of the data flow within a form. A form stores its data in three different
* representations:
*
* (1) the "model" format required by the form's object
* (2) the "normalized" format for internal processing
* (3) the "view" format used for display
*
* A date field, for example, may store a date as "Y-m-d" string (1) in the
* object. To facilitate processing in the field, this value is normalized
* to a DateTime object (2). In the HTML representation of your form, a
* localized string (3) is presented to and modified by the user.
*
* In most cases, format (1) and format (2) will be the same. For example,
* a checkbox field uses a Boolean value for both internal processing and
* storage in the object. In these cases you simply need to set a value
* transformer to convert between formats (2) and (3). You can do this by
* calling addViewTransformer().
*
* In some cases though it makes sense to make format (1) configurable. To
* demonstrate this, let's extend our above date field to store the value
* either as "Y-m-d" string or as timestamp. Internally we still want to
* use a DateTime object for processing. To convert the data from string/integer
* to DateTime you can set a normalization transformer by calling
* addNormTransformer(). The normalized data is then converted to the displayed
* data as described before.
*
* The conversions (1) -> (2) -> (3) use the transform methods of the transformers.
* The conversions (3) -> (2) -> (1) use the reverseTransform methods of the transformers.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Form implements \IteratorAggregate, FormInterface
{
...
}
编辑:这是来自 Sf 表单组件(合)作者的视频,他在其中解释了数据格式并给出了规范化格式使用的示例 -> https://youtu.be/Q80b9XeLUEA?t=7m6s
所以,基本上,每个表单都有三种不同格式的数据。前两个是:模型数据 - 您在域模型中使用的数据,以及视图数据 - 您通常在 HTML 中输出为字符串或在提交前输入表单字段的数据。
两个简单的示例是 TextType 和 NumberType。 TextType中,模型数据为字符串,视图数据为字符串。
在 NumberType 中,模型数据是浮点数 - 在您的应用程序中,您处理的是浮点数类型,而视图数据是本地化的字符串。
但是,另一方面,如果我们看一下 DateType,事情会有点复杂,因为模型数据可能是字符串 ('YYYY-MM-DD')、整数(unix 时间戳)、数组或 DateTime 对象。视图数据可以是本地化字符串或数组。
例如,如果你想写一个事件监听器,你不能确定你会得到什么数据格式:
class MyDateType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add...
->addEventListener(
FormEvents::FormEvents::SUBMIT,
array($this, 'onSubmit')
)
;
}
public function onSubmit(FormEvent $event)
{
// BUT WHAT FORMAT DO I GET???
$data = $event->getForm()->getData();
}
}
幸运的是,Sf表格还有第三种数据格式——归一化格式。该格式是静态的 - 您始终知道您将获得什么,它始终是相同的数据类型!
public function onSubmit(FormEvent $event)
{
// $data will be DateTime object!
$data = $event->getForm()->getNormData();
}
简短的解释/简化,当我开始学习 symfony 形式时,我曾经用来记住这些事情:
- 模型数据:Model/Entity/Whatever形式的数据。就是你的数据源数据格式
- Norm数据:Form字段表单中的数据。如果你有
CollectionType
,例如,你有一个数组,如果你有一个DateTimeType
,你有一个DateTime
等等 - 查看数据:查看表单中的数据。
基本上,如果您的格式 "consistent" 介于这些 "layers" 之间,您永远(*)不需要创建转换器。
只是为每种类型做一个例子:
型号 --> 标准
如果您有一个实体(模型数据)并且您的表单中有一个EntityType
字段(规范数据 ), 你不需要使用任何变压器
如果您有一个实体(模型数据)并且您有一个 TextType
字段来表示您的实体,您需要使用 ModelTransformer
作为你的格式不一致
规范 --> 视图
(*) 任何 DateType
或 DateTimeType
都有一个直接插入数据类型的转换器:用于从视图(用户)日期格式(时区)和规范(或模型)格式转换(时区)
正如您在此处看到的,转换不仅在非一致数据类型之间发生,而且在同一类型内发生。
你也可以检查this presentation
提醒一句,ViewData 可以变成 ModelData,反之亦然,这完全违背了此处提供的解释,您可能会感到困惑。它发生在几乎所有真实的单词案例中。
这取决于形式是否复合。复合表单就是有多个字段的表单,所以基本上都是。
参见:
line 634 send to ViewTransformer mix of view data (from main form) and model data (from children forms). Is it really expected?
是的 :) 原因我在上面已经解释过了。
继续:
简单表单=>查看数据==请求数据
复合形式=>查看数据==(data_class|数组)映射子模型数据,使用DataMapper。
来源:https://github.com/symfony/symfony/issues/22371#issuecomment-293494324
并且:
Internally the compound form uses its view data to map the data of the children.
我做了更多的研究:
As you say the compound option determines if PropertyPathMapper will be used. That's OK.
->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null)
Also as you say the Form class is using the mapper to map the view data to the forms. That's OK too.
$this->config->getDataMapper()->mapDataToForms($viewData, $iterator);
Then PropertyPathMapper mapper is setting the data on the forms. Hmm...
$form->setData($this->propertyAccessor->getValue($data, $propertyPath));
Why PropertyPathMapper trough Form is setting ViewData on forms that expect ModelData?
public function setData($modelData);
mapper中的ViewData是怎么变成ModelData的?为什么 ModelData 没有映射到表单上?为什么
data_class
适用于 ViewData 而不是 ModelData 更有意义?
来源:https://github.com/symfony/symfony/issues/20880#issuecomment-267129575