如何使用数据变形金刚吗

编辑该页面

警告:你浏览的文档欧宝官网下载appob娱乐下载Symfony 5.3,不再维护。

这个页面的更新版本Symfob娱乐下载ony 6.2(当前的稳定版本)。

如何使用数据变形金刚吗

数据变压器用于将一个字段的数据转化为一个格式,可以显示在一个表单(并重新提交)。他们已经在内部使用了许多字段类型。例如,DateType字段可以呈现为一个yyyy-MM-dd格式化的输入文本框。在内部,一个数据变压器转换开始DateTime领域进入的价值yyyy-MM-dd字符串的形式呈现,然后回一个DateTime在提交对象。

谨慎

当一个表单字段inherit_data选项设置为真正的变压器、数据应用于这一领域。

另请参阅

如果,改变一个值的表示,而是需要值映射到一个表单字段,您应该使用数据映射器。看看何时以及如何使用数据映射器

示例# 1:将字符串数组从用户输入的表单数据标签

假设你有一个任务形式标记文本类型:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21日22日23日24日25
/ / src /形式/类型/ TaskType.php名称空间应用程序\形式\类型;使用应用程序\实体\任务;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextType;使用ob娱乐下载\组件\形式\FormBuilderInterface;使用ob娱乐下载\组件\OptionsResolver\OptionsResolver;/ /……TaskType扩展AbstractType{公共函数buildForm(FormBuilderInterface美元构建器数组,美元选项):无效{美元构建器- >add (“标签”,TextType::类);}公共函数configureOptions(OptionsResolver美元解析器):无效{美元解析器- >setDefaults ([“data_class”= >任务::类,]);}/ /……}

在内部的标签被存储为一个数组,但显示给用户作为普通的逗号分隔字符串,使它们更容易编辑。

这是一个完美的将自定义数据变压器附加到的时间标签字段。这是最简单的方法CallbackTransformer类:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30
/ / src /形式/类型/ TaskType.php名称空间应用程序\形式\类型;使用ob娱乐下载\组件\形式\CallbackTransformer;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextType;使用ob娱乐下载\组件\形式\FormBuilderInterface;/ /……TaskType扩展AbstractType{公共函数buildForm(FormBuilderInterface美元构建器数组,美元选项):无效{美元构建器- >add (“标签”,TextType::类);美元构建器- >get (“标签”)- >addModelTransformer (CallbackTransformer (函数(美元tagsAsArray){/ /数组转换成一个字符串返回内爆(”、“,美元tagsAsArray);},函数(美元tagsAsString){/ /将字符串返回一个数组返回爆炸(”、“,美元tagsAsString);}));}/ /……}

CallbackTransformer有两个回调函数作为参数。首先将原始值转换成格式,将用于呈现。第二个效果恰恰相反:它将提交的值回在代码中您将使用的格式。

提示

addModelTransformer ()方法接受任何对象实现DataTransformerInterface——所以您可以创建自己的类,而不是把所有的逻辑形式(参见下一节)。

您还可以添加变压器,当添加字段通过改变格式略:

1 2 3 4 5 6 7
使用ob娱乐下载\组件\形式\扩展\核心\类型\TextType;美元构建器- >add (美元构建器- >创建(“标签”,TextType::类)- >addModelTransformer (…));

例2:将一个问题数量转变为一个实体问题

说你有多对一关系从任务的实体问题的实体(即每个任务都有一个可选的外键对其相关问题)。添加一个列表框与所有可能的问题最终会得到真的长,需要很长时间才能加载。相反,你决定你想添加一个文本框,用户可以输入号码的问题。

首先设置文本框像正常:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27
/ / src /形式/类型/ TaskType.php名称空间应用程序\形式\类型;使用应用程序\实体\任务;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextareaType;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextType;/ /……TaskType扩展AbstractType{公共函数buildForm(FormBuilderInterface美元构建器数组,美元选项):无效{美元构建器- >add (“描述”,TextareaType::类)- >add (“问题”,TextType::类);}公共函数configureOptions(OptionsResolver美元解析器):无效{美元解析器- >setDefaults ([“data_class”= >任务::类,]);}/ /……}

好的开始!但是如果你停止在这里,提交了表单,任务的问题属性将一个字符串(如。“55”)。你怎么能把这变成一个问题实体提交吗?

创建一个变压器

你可以用CallbackTransformer就像早些时候。但由于这是一个更复杂的,创建一个新的变压器类的TaskType类更简单的形式。

创建一个IssueToNumberTransformer类:它将负责号码和转换的问题问题对象:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
/ / src /形式/ DataTransformer / IssueToNumberTransformer.php名称空间应用程序\形式\DataTransformer;使用应用程序\实体\问题;使用学说\ORM\EntityManagerInterface;使用ob娱乐下载\组件\形式\DataTransformerInterface;使用ob娱乐下载\组件\形式\异常\TransformationFailedException;IssueToNumberTransformer实现了DataTransformerInterface{私人美元entityManager;公共函数__construct(EntityManagerInterface美元entityManager){美元- >entityManager =美元entityManager;}/ * * *转换对象(问题),一个字符串(数值)。”* *@param问题|零美元问题* /公共函数变换(美元问题):字符串{如果(= = =美元问题){返回;}返回美元问题- >getId ();}/ * * *转换字符串(数量)一个对象(问题)。* *@param字符串$ issueNumber *@throws没有找到TransformationFailedException如果对象(问题)。* /公共函数reverseTransform(美元issueNumber):哦?问题{/ /没有问题号码吗?这是可选的,所以没关系如果(!美元issueNumber){返回;}美元问题=美元- >entityManager- >getRepository(问题::类)/ /查询这个id的问题- >找到(美元issueNumber);如果(= = =美元问题){/ /验证错误原因/ /这个信息没有显示给用户/ /看到invalid_message选项TransformationFailedException (sprintf (的数量的问题“% s”不存在!”,美元issueNumber));}返回美元问题;}}

就像第一个例子,变压器有两个方向。的变换()方法负责将在代码中使用的数据转换为一种格式,可以呈现在表单(例如一个问题对象的id一个字符串)。的reverseTransform ()方法的效果恰恰相反:它转换回你想要的格式提交的值(例如转换id问题对象)。

导致验证错误,抛出一个TransformationFailedException。但消息传递给这个例外不会显示给用户。你会设置的消息invalid_message选项(见下文)。

请注意

传递给变换()方法,你的变压器应该返回一个等价的值的类型是改变(如一个空字符串,0为整数或0.0浮动)。

使用变压器

接下来,您需要使用IssueToNumberTransformer对象的内部TaskType并将其添加到问题字段。没问题!添加一个__construct ()方法和type-hint新类:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34
/ / src /形式/类型/ TaskType.php名称空间应用程序\形式\类型;使用应用程序\形式\DataTransformer\IssueToNumberTransformer;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextareaType;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextType;/ /……TaskType扩展AbstractType{私人美元变压器;公共函数__construct(IssueToNumberTransformer美元变压器){美元- >变压器=美元变压器;}公共函数buildForm(FormBuilderInterface美元构建器数组,美元选项):无效{美元构建器- >add (“描述”,TextareaType::类)- >add (“问题”,TextType::类,/ /验证消息如果数据变压器失败“invalid_message”= >“这不是一个有效的问题数量”]);/ /……美元构建器- >get (“问题”)- >addModelTransformer (美元- >变压器);}/ /……}

当变压器将抛出一个异常,invalid_message显示给用户。而不是每次都显示相同的信息,您可以设置数据变压器使用的终端用户错误消息setInvalidMessage ()方法。它还允许您包括用户价值:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29
/ / src /形式/ DataTransformer / IssueToNumberTransformer.php名称空间应用程序\形式\DataTransformer;使用ob娱乐下载\组件\形式\DataTransformerInterface;使用ob娱乐下载\组件\形式\异常\TransformationFailedException;IssueToNumberTransformer实现了DataTransformerInterface{/ /……公共函数reverseTransform(美元issueNumber):哦?问题{/ /……如果(= = =美元问题){美元privateErrorMessage= sprintf (的数量的问题“% s”不存在!”,美元issueNumber);美元publicErrorMessage=给定的”{{value}}”值不是一个有效的问题数量。;美元失败=TransformationFailedException (美元privateErrorMessage);美元失败- >setInvalidMessage (美元publicErrorMessage,(“{{value}}”= >美元issueNumber]);美元失败;}返回美元问题;}}

就是这样!如果你使用默认的服务。yaml的配置,Sob娱乐下载ymfony会自动知道通过你TaskType的一个实例IssueToNumberTransformer多亏了自动装配可以使用autoconfigure。否则,注册表单类作为服务标记它form.type标签。

现在,你可以用你的TaskType:

1 2 3 4
/ /例如:在一个控制器美元形式=美元- >createForm (TaskType::类,美元任务);/ /……

酷,你已经完成了!您的用户将能够在文本字段中输入一个问题数量,这将被转换回一个问题对象。这意味着,提交成功后,表单组件将通过一个真实的问题对象任务::setIssue ()而不是数量的问题。

如果这个问题没有发现,将会创建一个形状误差对该字段及其错误消息可以控制的invalid_message场的选择。

谨慎

添加时要小心你的变形金刚。例如,下面是错误的,随着变压器将应用于整个表单,而不是仅仅这一领域:

1 2 3 4
/ /这是错误的——变压器将适用于整个表单/ /上面看到正确的代码示例美元构建器- >add (“问题”,TextType::类)- >addModelTransformer (美元变压器);

创建一个可重用issue_selector字段

在上面的示例中,您使用变压器正常文本字段。但是如果你这个变换,它可能是更好的创建一个自定义字段类型。自动做这个。

首先,创建自定义字段类型类:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35
/ / src /形式/ IssueSelectorType.php名称空间应用程序\形式;使用应用程序\形式\DataTransformer\IssueToNumberTransformer;使用ob娱乐下载\组件\形式\AbstractType;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextType;使用ob娱乐下载\组件\形式\FormBuilderInterface;使用ob娱乐下载\组件\OptionsResolver\OptionsResolver;IssueSelectorType扩展AbstractType{私人美元变压器;公共函数__construct(IssueToNumberTransformer美元变压器){美元- >变压器=美元变压器;}公共函数buildForm(FormBuilderInterface美元构建器数组,美元选项):无效{美元构建器- >addModelTransformer (美元- >变压器);}公共函数configureOptions(OptionsResolver美元解析器):无效{美元解析器- >setDefaults ([“invalid_message”= >“不存在选择的问题”]);}公共函数getParent():字符串{返回TextType::类;}}

太棒了!这将呈现像文本字段(getParent ()),但会自动数据变压器一个默认值invalid_message选择。

只要你使用自动装配可以使用autoconfigure,您可以立即开始使用表单:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/ / src /形式/类型/ TaskType.php名称空间应用程序\形式\类型;使用应用程序\形式\DataTransformer\IssueToNumberTransformer;使用ob娱乐下载\组件\形式\扩展\核心\类型\TextareaType;/ /……TaskType扩展AbstractType{公共函数buildForm(FormBuilderInterface美元构建器数组,美元选项):无效{美元构建器- >add (“描述”,TextareaType::类)- >add (“问题”,IssueSelectorType::类);}/ /……}

提示

如果你不使用自动装配可以使用autoconfigure,请参阅如何创建一个自定义表单字段类型如何配置你的新IssueSelectorType

模型和视图变形金刚

在上面的例子中,变压器被用作变压器“模型”。事实上,有两个不同类型的变压器和三种不同类型的基础数据。

在任何形式,三种不同类型的数据:

  1. 模型数据——这是在应用程序中使用的数据格式(如一个问题对象)。如果你叫形式::getData ()形式::setData (),你在处理“模型”的数据。
  2. 规范数据——这是一个规范化的版本你的数据和通常一样的“模型”数据(虽然不是在我们的示例中)。它不是常用的直接。
  3. 视图数据——这是用来填写表单字段的格式,自己。这也是用户提交数据的格式。当你打电话形式:提交(元数据),元数据在“视图”数据格式。

两种不同类型的变压器帮助转换与每一种类型的数据:

变形金刚模型:
  • 变换():“模型数据”= >“规范数据”
  • reverseTransform ():“规范数据”= >“模型数据”
看变形金刚:
  • 变换():“规范数据”= >“查看数据”
  • reverseTransform ():“查看数据”= >“规范数据”

变压器需要取决于您的情况。

使用视图变压器,电话addViewTransformer ()

谨慎

变形金刚和小心模型集合字段类型。孩子早期创建的集合PRE_SET_DATA由其ResizeFormListener和他们的数据填充后的规范化数据。所以你的模型变压器不能减少集合内的物品(即过滤掉一些物品),在这种情况下,收集了一些空的孩子结束。

一个可能的解决方法,限制可能不直接使用底层对象,而是一个DTO(数据传输对象)相反,实现这样的变换不兼容的数据结构。

为什么使用模型的变压器?

在这个例子中,字段是一个文本领域,一个文本字段总是将一个简单的、标量格式在“规范”和“视图”格式。出于这个原因,“模型”是最合适的变压器变压器(的/转换规范格式-字符串问题数字的模型格式-问题对象)。

变压器的区别是微妙的,你应该考虑的“常态”数据字段应该是。例如,“规范”的数据文本字段是一个字符串,但是是一个DateTime对象的一个日期字段。

提示

作为一般规则,规范化数据应该包含尽可能多的信息。

这项工作,包括代码示例,许可下Creative Commons冲锋队3.0许可证。
ob娱乐下载Symfony 5.3支持通过JoliCode