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?"中的下一段对我没有任何意义。
答案 0 :(得分:16)
我发现的最佳解释是在Symfony的Form类描述中:
<?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表单组件(合作)作者的视频,其中他解释了数据格式并给出了标准化格式使用的示例 - &gt; https://youtu.be/Q80b9XeLUEA?t=7m6s
因此,基本上,每个表单都有三种不同格式的数据。前两个是:模型数据 - 您在域模型中使用的数据,以及视图数据 - 您通常以HTML格式输出的数据,或者在提交之前输入表单字段。
两个简单的例子是TextType和NumberType。 在TextType中,模型数据是字符串,视图数据是字符串。
在NumberType中,模型数据是浮点数 - 在您的应用程序中,您正在处理浮点类型,而视图数据是本地化字符串。
但是,另一方面,如果我们看一下DateType,事情有点复杂,因为模型数据可能是字符串(&#39; YYYY-MM-DD&#39;),一个整数(unix timestamp),一个数组或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();
}
答案 1 :(得分:1)
当我开始学习symfony形式时,我曾经习惯用来记住这些事情的简短解释/简化:
CollectionType
,那么您有一个数组;如果您有DateTimeType
,那么您有DateTime
等等基本上,如果您的格式是&#34;一致&#34;在这些&#34;层之间,你永远不会(*)需要创建一个变压器。
只是为每个类型做一个例子:
如果您有一个实体(模型数据)并且表单中有{{1>}字段(规范数据),那么您就不会需要使用任何变压器
如果您有一个实体(模型数据)并且您有EntityType
字段来表示您的实体,那么您需要使用TextType
,因为您的格式不一致
(*)任何ModelTransformer
或DateType
都有一个直接插入数据类型的转换器:用于转换视图(用户)日期格式(时区)和规范(或模型)格式(时区) )
正如您在此处所看到的,转换不仅在非一致数据类型之间,而且在相同类型之间。
您也可以查看this presentation
答案 2 :(得分:1)
作为警告,您可能会被ViewData成为ModelData,反之亦然,完全违背此处提供的解释。它几乎发生在所有真实的单词案例中。
这取决于表单是否复合。复合形式是具有多个字段的形式,基本上都是所有字段。
请参阅:
第634行发送到ViewTransformer混合视图数据(来自主窗体)和模型数据(来自子窗体)。真的是期待吗?
是的:)是我上面解释的原因。
要恢复:
简单形式=&gt;查看数据==请求数据
复合形式=&gt; view data ==(data_class | array)使用DataMapper映射子模型数据。
来源:https://github.com/symfony/symfony/issues/22371#issuecomment-293494324
和
复合形式在内部使用其视图数据来映射子项的数据。
我做了更多的研究:
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);
ViewData如何在映射器中更改为ModelData?为什么ModelData没有映射到表单上?为什么
data_class
适用于ViewData而不适用于更适合的ModelData?
来源:https://github.com/symfony/symfony/issues/20880#issuecomment-267129575
答案 3 :(得分:0)