simplethings / form-serializer-bundle
基于表单类型将对象图序列化和反序列化为XML/JSON
Requires
- symfony/form: 2.1.*
- symfony/http-foundation: 2.1.*
- symfony/serializer: 2.1.*
Requires (Dev)
- jms/serializer-bundle: dev-master
This package is auto-updated.
Last update: 2024-09-11 01:45:34 UTC
README
帮助解决Serializer/Form组件API不匹配的Bundle。这种不匹配会导致控制器中的代码无法重用,使每个应用都通过重复实现一切而膨胀。目前几乎不可能在同一个控制器操作中重用REST-API调用和基于HTML/表单的提交。此外,所有当前的序列化组件都存在一个共同缺陷:它们无法将对象图反序列化(更新)。更新对象图是Form组件已经解决的问题(完美!)。
此bundle通过挂钩到Form框架来解决这些问题。它允许使用表单类型实现对象的序列化器。对于反序列化,它使用与“常规”表单请求完全相同的API。
Form组件是一个非常优秀的序列化库,但到目前为止,它只有一个实现:HTML表单。此bundle添加了对将序列化编码器挂钩到此过程的支持,默认支持XML和JSON。
新的表单选项
使用此bundle,您将获得新的表单类型选项。重写“form”字段以具有以下附加配置键
serialize_xml_name
- 指定根XML名称或列表条目XML名称的元素,具体取决于其在父或子元素上的定义。(默认:entry)serialize_xml_value
- 如果为true,此字段将是父字段的XML值。如果嵌套类型具有一些属性和一个值,则很有用。(默认:false)serialize_xml_attribute
- 如果为true,此字段将作为父元素上的属性在XML中渲染,而不是作为元素。(默认:false)serialize_xml_inline
- 如果为true,则不会为元素集合渲染集合包装元素。如果为false,则包装所有元素。(默认:true)serialize_name
- 如果需要从默认的驼峰式命名策略(将驼峰式转换为下划线)中偏离,则指定序列化形式中元素的名称。(默认:false)serialize_only
- 如果为true,则字段将从FormView
中删除,因此只存在于序列化数据(json,xml)中
用法
此bundle在Symfony DIC中定义了一个新的服务以序列化表单
class UserController extends Controller { public function showAction(User $user) { $serializer = $this->get('form_serializer'); $xml = $serializer->serialize($user, new UserType(), 'xml'); return new Response($xml, 200, array('Content-Type' => 'text/xml')); } }
FormListener的API在它实现的FormSerializerInterface
上进行了文档说明
interface FormSerializerInterface { /** * Serialize a list of objects, where each element is serialized based on a * form type. * * @param array|Traversable $list * @param FormTypeInterface $type * @param string $format * @param string $xmlRootName * * @return string */ public function serializeList($list, $type, $format, $xmlRootName = 'entries'); /** * Serialize an object based on a form type, form builder or form instance. * * @param mixed $object * @param FormTypeInterface|FormBuilderInterface|FormInterface $typeBuilder * @param string $format * * @return string */ public function serialize($object, $typeBuilder, $format); }
此bundle还在表单框架内部注册了一个监听器,将XML和JSON请求绑定到表单。只需像以下示例中那样调用$form->bind($request)
即可。
如果您想将JMS Serializer基于配置转换为FormTypes,可以使用包含的命令
php app/console simplethings:convert-jms-metadata "className"
由于JMS Serializer会自动为每个类构建元数据,因此您可以使用此命令为您生成任何现有类的表单类型。
配置
默认DIC(config.yml)配置
simple_things_form_serializer: include_root_in_json: false application_xml_root_name: ~ naming_strategy: camel_case encoders: xml: true json: true
名为simple_things_form_serializer.encoder
的依赖注入标签,用于添加更多编码器。
示例
考虑一个通常的表单,扩展了一些有关序列化的详细信息
namespace Acme\DemoBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class UserType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('username', 'text') ->add('email', 'email') ->add('country', 'entity') ->add('addresses', 'collection', array('type' => 'address', 'serialize_xml_name' => 'address')) ->add('created', 'datetime', array('read_only' => true)) ; } public function getName() { return 'user'; } public function setDefaultOptions(OptionsResolverInterface $options) { $options->setDefaults(array( 'data_class' => 'Acme\DemoBundle\Entity\User', 'serialize_xml_name' => 'user', )); } }
使用序列化器
$serializer = $this->get('form_serializer'); $data = $serializer->serialize($user, new UserType(), 'xml');
生成
<user> <username>beberlei</username> <email>kontakt@beberlei.de</email> <country>de</country> <addresses> <address> <street>Foostreet 1</street> </address> </addresses> <created>2012-07-10</created> </user>
或者如果您使用JSON
{ "user": { "username": "beberlei", "email": "kontakt@beberlei.de", "country": "de", "addresses": [ {"street": "Foostreet 1"} ], "created": "2012-07-10" } }
反序列化看起来很熟悉
class UserController extends Controller { /** * @Method("POST") */ public function editAction(Request $request) { $em = $this->get('doctrine.orm.default_entity_manager'); $user = $em->find('Acme\DemoBundle\Entity\User', $request->get('id')); $form = $this->createForm(new UserType(), $user); $form->bind($request); if ( ! $form->isValid()) { return $this->renderFormFailure("MyBundle:User:edit.html.twig", $form, array('user' => $user)); } // do some business logic here $em->flush(); return $this->formRedirect($form, $this->generateUrl('user_show', array('id' => $user->getId()), 201); } /* either render the form errors as xml/json or the html form again based on " _format" */ public function renderFormFailure($template, FormInterface $form, $parameters) { } /* redirect OR 201 created, based on the "_format" */ public function formRedirect() { } }
这几乎就像一本教科书中的表单请求。唯一不同的是,我们必须使用“renderFormView”和“formRedirect”方法来生成响应对象。
renderFormView
将根据响应格式决定要执行的操作。- 当格式为html时,显示一个表单
- 当传递的表单尚未绑定时,显示HTTP 405错误
- 显示HTTP 412预条件失败,表单错误序列化为XML或JSON
formRedirect
将根据响应格式进行决策- 如果其是html(或配置选项
use_forwards = false
),则重定向到指定的URL - 如果其是xml或json(并且配置选项
use_forwards = true
),则转发到路由
- 如果其是html(或配置选项