如何使用数据转换器
编辑本页警告:您正在浏览的文档欧宝官网下载appob娱乐下载Symfony 2.0,现已不再维护。
读本页的更新版本用于Syob娱乐下载mfony 6.2(当前稳定版本)。
如何使用数据转换器
您经常会发现需要将用户在表单中输入的数据转换为其他数据,以便在程序中使用。您可以很容易地在控制器中手动完成这一操作,但是如果您想在不同的地方使用这个特定的表单呢?
假设你有一个任务到问题的一对一关系,例如,一个任务有一个可选的问题链接到它。添加一个包含所有可能问题的列表框最终会导致一个非常长的列表框,其中不可能找到任何东西。您可能希望添加一个文本框,用户只需在其中输入问题编号。
你可以尝试在控制器中这样做,但这不是最好的解决方案。如果将此问题自动转换为issue对象会更好。这就是数据转换器发挥作用的地方。
创建变压器
首先,创建一个' IssueToNumberTransformer '类——这个类将负责在issue编号和issue对象之间进行转换:
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 66 67 68
/ / src / Acme / TaskBundle /形式/ DataTransformer / IssueToNumberTransformer.php名称空间Acme\TaskBundle\形式\DataTransformer;使用ob娱乐下载\组件\形式\DataTransformerInterface;使用ob娱乐下载\组件\形式\异常\TransformationFailedException;使用学说\常见的\持久性\ObjectManager;使用Acme\TaskBundle\实体\问题;类IssueToNumberTransformer实现了DataTransformerInterface{/ * * *@varObjectManager * /私人$om;/ * * *@paramObjectManager $om */公共函数__construct(ObjectManager$om){$这->om =$om;}/** *将对象(issue)转换为字符串(number)。* *@paramIssue|null $ Issue *@return字符串* /公共函数变换($问题){如果(零===$问题) {返回"";}返回$问题->getNumber ();}/** *将字符串(数字)转换为对象(问题)。* *@param字符串$number * *@return发布|null * *@throws如果object (issue)未找到,TransformationFailedException异常。* /公共函数reverseTransform($数量){如果(!$数量) {返回零;}$问题=$这->om->getRepository (“AcmeTaskBundle:问题”)->findOneBy (数组(“数量”= >$数量));如果(零===$问题) {扔新TransformationFailedException (sprintf (“数字“%s”不存在问题!”,$数量));}返回$问题;}}
提示
如果您希望在输入未知数字时创建一个新问题,则可以实例化它,而不是抛出TransformationFailedException
.
使用变压器
现在已经构建了转换器,您只需要以某种形式将它添加到问题字段中。
您也可以使用转换器,而无需通过调用来创建新的自定义表单类型
prependNormTransformer
(或appendClientTransformer
——看规范和客户端转换器):12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21
使用Acme\TaskBundle\形式\DataTransformer\IssueToNumberTransformer;类TaskType扩展AbstractType{公共函数buildForm(FormBuilder$构建器数组,$选项){/ /……//假设实体管理器是作为一个选项传入的$entityManager=$选项[“新兴市场”];$变压器=新IssueToNumberTransformer ($entityManager);//添加一个普通的文本字段,但添加你的变压器$构建器->add ($构建器->创建(“问题”,“文本”)->prependNormTransformer ($变压器));}/ /……}
本例要求您在创建表单时将实体管理器作为一个选项传入。稍后,您将学习如何创建自定义问题
字段类型,以避免在你的控制器中这样做:
1 2 3
$taskForm=$这->createForm (新TaskType (),$任务,数组(“新兴市场”= >$这->getDoctrine ()->getEntityManager ()));
酷,你完成了!您的用户将能够在文本字段中输入问题编号,它将被转换回问题对象。这意味着,在成功绑定之后,Form框架将传递一个真正的Issue对象给任务::setIssue ()
而不是发行号。
方法将为该字段创建一个表单错误,并且其错误消息可以用invalid_message
场的选择。
谨慎
注意,在添加字段时,添加转换器需要使用稍微复杂一些的语法。以下是错误的,因为转换器将被应用到整个表单,而不仅仅是这个字段:
1 2 3 4
//这是错误的- transformer将被应用到整个表单//查看上面的示例以获得正确的代码$构建器->add (“问题”,“文本”)->prependNormTransformer ($变压器);
规范和客户端转换器
在上面的例子中,变压器被用作“标准”变压器。事实上,有两种不同类型的变压器和三种不同类型的底层数据。
在任何形式下,三种不同类型的数据是:
1)应用程序数据-这是在您的应用程序中使用的格式的数据(例如问题
对象)。如果你打电话形式:getData
或形式:setData
,您正在处理“应用程序”数据。
2)规范数据-这是数据的规范化版本,通常与“应用程序”数据相同(虽然在本例中不是这样)。通常不直接使用。
3)客户端数据-这是用来填写表单字段本身的格式。它也是用户提交数据的格式。当你打电话时形式:绑定(元数据)
,元数据
是“客户端”数据格式。
两种不同类型的变压器有助于转换这些类型的数据:
- 规范《变形金刚》:
-
变换
: "app data" => "norm data"reverseTransform
: "norm data" => "app data"
- 客户端变形金刚:
-
变换
: "norm data" => "客户端数据"reverseTransform
: "client data" => "norm data"
您需要哪种变压器取决于您的情况。
要使用客户端转换器,请调用appendClientTransformer
.
那么为什么要使用范数转换器呢?
在本例中,字段为a文本
字段,而文本字段总是被期望是“规范”和“客户端”格式中的简单标量格式。由于这个原因,最合适的变压器是“规范”变压器(它转换为/从<新兴市场>规范新兴市场>格式-字符串发行号-到<新兴市场>应用程序新兴市场>format -发布对象)。
转换器之间的差异是微妙的,您应该始终考虑一个字段的“规范”数据应该是什么。例如,a的“规范”数据文本
字段是一个字符串,但是是DateTime
对象的日期
字段。
在自定义字段类型中使用transformer
在上面的示例中,您将变压器应用到法线上文本
字段。这很简单,但有两个缺点:
1)无论何时为问题编号添加字段,您都需要始终记住应用转换器
2)你需要担心通过考试新兴市场
选项,当您创建使用转换器的表单时。
由于这些原因,您可以选择创建创建自定义字段类型.首先,创建自定义字段类型类:
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 37 38 39 40 41 42 43 44 45 46
/ / src / Acme / TaskBundle /形式/类型/ IssueSelectorType.php名称空间Acme\TaskBundle\形式\类型;使用ob娱乐下载\组件\形式\AbstractType;使用ob娱乐下载\组件\形式\FormBuilder;使用Acme\TaskBundle\形式\DataTransformer\IssueToNumberTransformer;使用学说\常见的\持久性\ObjectManager;类IssueSelectorType扩展AbstractType{/ * * *@varObjectManager * /私人$om;/ * * *@paramObjectManager $om */公共函数__construct(ObjectManager$om){$这->om =$om;}公共函数buildForm(FormBuilder$构建器数组,$选项){$变压器=新IssueToNumberTransformer ($这->om);$构建器->prependNormTransformer ($变压器);}公共函数getDefaultOptions(数组$选项){返回数组(“invalid_message”= >“所选问题不存在”,);}公共函数getParent(数组$选项){返回“文本”;}公共函数getName(){返回“issue_selector”;}}
接下来,将您的类型注册为服务并标记为form.type
这样它就被识别为自定义字段类型:
- YAML
- XML
- PHP
1 2 3 4 5 6
服务:acme_demo.type.issue_selector:类:Acme \ TaskBundle \ \ \ IssueSelectorType型形式参数:(“@doctrine.orm.entity_manager”)标签:-{名称:form.type,别名:issue_selector}
1 2 3 4
<服务id=“acme_demo.type.issue_selector”类=“Acme \ TaskBundle \ \ \ IssueSelectorType型”><论点类型=“服务”id=“doctrine.orm.entity_manager”/><标签的名字=“form.type”别名=“issue_selector”/>服务>
1 2 3 4 5 6 7 8
$容器->setDefinition (“acme_demo.type.issue_selector”,数组(新引用(“doctrine.orm.entity_manager”)))->addTag (“form.type”,数组(“别名”= >“issue_selector”,));
现在,无论何时你需要使用你的特殊issue_selector
字段类型,很简单:
12 3 4 5 6 7 8 9 10 11 12 13 14 16 17 18 19 20 21
/ / src / Acme / TaskBundle /形式/类型/ TaskType.php名称空间Acme\TaskBundle\形式\类型;使用ob娱乐下载\组件\形式\AbstractType;使用ob娱乐下载\组件\形式\FormBuilder;类TaskType扩展AbstractType{公共函数buildForm(FormBuilder$构建器数组,$选项){$构建器->add (“任务”)->add (“dueDate”,零,数组(“部件”= >“single_text”))->add (“问题”,“issue_selector”);}公共函数getName(){返回“任务”;}}