形成标准数据与查看数据 - 有什么区别?

时间:2016-12-13 07:58:45

标签: php symfony symfony-forms

The documentation说:

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?"中的下一段对我没有任何意义。

4 个答案:

答案 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对象。视图数据可以是本地化字符串或数组。

enter image description here

例如,如果你想编写一个事件监听器,你就不能确定你会得到什么样的数据格式:

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表格有第三种数据格式 - 规范化格式。这种格式是静态的 - 你总是知道你会得到什么,它总是相同的数据类型!

enter image description here

 public function onSubmit(FormEvent $event)
 {
     // $data will be DateTime object!
     $data = $event->getForm()->getNormData();
 }

答案 1 :(得分:1)

当我开始学习symfony形式时,我曾经习惯用来记住这些事情的简短解释/简化:

  • 模型数据:模型/实体/无论何种形式的数据。它是您的数据源数据格式
  • 规范数据:表单字段中的数据。例如,如果您有CollectionType,那么您有一个数组;如果您有DateTimeType,那么您有DateTime等等
  • 查看数据:查看表单中的数据。

基本上,如果您的格式是&#34;一致&#34;在这些&#34;层之间,你永远不会(*)需要创建一个变压器。

只是为每个类型做一个例子:

模型 - &gt;规范

如果您有一个实体(模型数据)并且表单中有{{1>}字段(规范数据),那么您就不会需要使用任何变压器

如果您有一个实体(模型数据)并且您有EntityType字段来表示您的实体,那么您需要使用TextType,因为您的格式不一致

规范 - &gt;图

(*)任何ModelTransformerDateType都有一个直接插入数据类型的转换器:用于转换视图(用户)日期格式(时区)和规范(或模型)格式(时区) )

正如您在此处所看到的,转换不仅在非一致数据类型之间,而且在相同类型之间。

您也可以查看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)

让我们以DateTimeType小部件为例。

模型数据是Datetime

标准数据为arrayin the documentation

视图数据是string(例如输入文本)