如何使用数据转换器

编辑本页

警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 4.2,现已不再维护。

本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。

如何使用数据转换器

数据转换器用于将字段的数据转换为可以在表单中显示的格式(并在提交时返回)。它们已经在内部用于许多字段类型。例如,DateType字段可以呈现为yyyy-MM-dd格式的输入文本框。在内部,数据转换器转换启动DateTime字段的值yyyy-MM-dd字符串来呈现窗体,然后返回为DateTime对象在提交时。

谨慎

属性时inherit_data选项设置为真正的,数据转换器并不应用于该领域。

另请参阅

如果不是转换值的表示形式,而是需要将值映射到表单字段并返回,则应该使用数据映射器。看看何时以及如何使用数据映射器

简单示例:将字符串标签从用户输入转换为数组

假设您有一个带有标记的Task表单文本类型:

12 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娱乐下载组件OptionsResolverOptionsResolver/ /……TaskType扩展AbstractType公共函数buildForm(FormBuilderInterface构建器数组,选项构建器->add (“标签”, TextType::类);}公共函数configureOptions(OptionsResolver解析器解析器->setDefaults ([“data_class”= >任务::类,]);}/ /……

在内部的标签存储为数组,但以逗号分隔的字符串显示给用户,以便于编辑。

这是一个完美的对象上附加自定义数据转换器的时间到了标签字段。最简单的方法是用CallbackTransformer类:

12 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(…));

更难的例子:将问题编号转换为问题实体

假设你有一个从任务实体到问题实体的多对一关系(即每个任务都有一个可选的外键指向其相关的问题)。添加一个包含所有可能问题的列表框最终会得到真的时间长,加载时间长。相反,您决定添加一个文本框,用户可以在其中输入问题编号。

首先像往常一样设置文本字段:

12 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类:它将负责从发行号和问题对象:

12 34 56 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 64 65
/ / src /形式/ DataTransformer / IssueToNumberTransformer.php名称空间应用程序形式DataTransformer使用应用程序实体问题使用学说ORMEntityManagerInterface使用ob娱乐下载组件形式DataTransformerInterface使用ob娱乐下载组件形式异常TransformationFailedExceptionIssueToNumberTransformer实现了DataTransformerInterface私人entityManager公共函数__construct(EntityManagerInterfaceentityManager->entityManager =entityManager;}/** *将对象(issue)转换为字符串(number)。* *@paramIssue|null $ Issue *@return字符串* /公共函数变换问题如果===问题){返回'';}返回问题->getId ();}/** *将字符串(数字)转换为对象(问题)。* *@param字符串$issueNumber *@return问题|零*@throws如果object (issue)未找到,TransformationFailedException异常。* /公共函数reverseTransformissueNumber//没有发行号?这是可选的,所以没关系如果(!issueNumber){返回;}问题->entityManager->getRepository(问题::类)//查询带有此id的问题->找到(issueNumber);如果===问题){//导致验证错误//该消息不显示给用户//查看invalid_message选项TransformationFailedException (sprintf (“数字“%s”不存在问题!”issueNumber));}返回问题;}}

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

若要导致验证错误,抛出TransformationFailedException.但是传递给这个异常的消息不会显示给用户。设置该消息invalid_message选项(见下文)。

请注意

传递给变换()方法,您的转换器应该返回它要转换到的类型的等效值(例如,空字符串,整数为0或浮点数为0.0)。

使用变压器

接下来,您需要使用IssueToNumberTransformer的内部对象TaskType把它加到问题字段。没问题!添加一个__construct ()方法和类型提示新类:

12 34 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名称空间应用程序形式类型使用应用程序形式DataTransformerIssueToNumberTransformer使用ob娱乐下载组件形式扩展核心类型TextareaType使用ob娱乐下载组件形式扩展核心类型TextType/ /……TaskType扩展AbstractType私人变压器公共函数__construct(IssueToNumberTransformer变压器->变压器=变压器;}公共函数buildForm(FormBuilderInterface构建器数组,选项构建器->add (“描述”, TextareaType::类)->add (“问题”, TextType::类,如果数据转换器失败,则发送验证消息“invalid_message”= >“这不是有效的发行号”]);/ /……构建器->get (“问题”->addModelTransformer (->变压器);}/ /……

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

现在你可以用你的TaskType

1 2 3 4
//例如,在控制器的某个地方形式->createForm (TaskType::类,任务);/ /……

酷,你完成了!您的用户将能够在文本字段中输入一个问题编号,该数字将被转换回issue对象。这意味着,在成功提交之后,Form组件将传递一个实问题对象任务::setIssue ()而不是发行号。

方法将为该字段创建一个表单错误,并且其错误消息可以用invalid_message场的选择。

谨慎

在添加变压器时要小心。例如,下面是错误的,因为转换器将被应用到整个表单,而不仅仅是这个字段:

1 2 3 4
//这是错误的- transformer将被应用到整个表单//查看上面的示例以获得正确的代码构建器->add (“问题”, TextType::类)->addModelTransformer (变压器);

创建一个可重用的issue_selector字段

在上面的示例中,您将变压器应用到法线上文本字段。但如果你经常做这个变换,可能会更好创建自定义字段类型.这是自动的。

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

12 34 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
/ / src /形式/ IssueSelectorType.php名称空间应用程序形式使用应用程序形式DataTransformerIssueToNumberTransformer使用学说常见的持久性ObjectManager使用ob娱乐下载组件形式AbstractType使用ob娱乐下载组件形式扩展核心类型TextType使用ob娱乐下载组件形式FormBuilderInterface使用ob娱乐下载组件OptionsResolverOptionsResolverIssueSelectorType扩展AbstractType私人变压器公共函数__construct(IssueToNumberTransformer变压器->变压器=变压器;}公共函数buildForm(FormBuilderInterface构建器数组,选项构建器->addModelTransformer (->变压器);}公共函数configureOptions(OptionsResolver解析器解析器->setDefaults ([“invalid_message”= >“所选问题不存在”]);}公共函数getParent()返回TextType::类;}}

太棒了!这将像文本字段(getParent ()),但会自动拥有数据转换器而且的良好默认值invalid_message选择。

只要你在用自动装配而且可以使用autoconfigure,你可以立即开始使用此表格:

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

提示

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

关于模型和视图变形金刚

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

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

  1. 模型数据-这是在您的应用程序中使用的格式的数据(例如问题对象)。如果你打电话形式::getData ()形式::setData (),您正在处理“模型”数据。
  2. 规范数据-这是数据的规范化版本,通常与“模型”数据相同(尽管在我们的例子中不是这样)。通常不直接使用。
  3. 视图数据-这是用来填写表单字段本身的格式。它也是用户提交数据的格式。当你打电话时形式:提交(元数据),元数据是“视图”数据格式。

两种不同类型的变压器帮助转换这些类型的数据:

变形金刚模型
  • 变换(): "model data" => "norm data"
  • reverseTransform (): "norm data" => "model data"
看变形金刚
  • 变换(): "norm data" => "view data"
  • reverseTransform (): "view data" => "norm data"

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

要使用视图转换器,请调用addViewTransformer ()

那么为什么要使用模型转换器呢?

在本例中,字段为a文本字段,而文本字段总是被期望是“norm”和“view”格式中的简单标量格式。由于这个原因,最合适的变压器是“模型”变压器(它转换为/从规范格式-字符串发行号-到模型format -发布对象)。

转换器之间的差异是微妙的,您应该始终考虑一个字段的“规范”数据应该是什么。例如,a的“规范”数据文本字段是一个字符串,但是是DateTime对象的日期字段。

提示

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

此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。