具有单一实体的Symfony表单集合

时间:2015-05-19 17:26:45

标签: php forms symfony fosrestbundle

也许这不是我正在寻找的收藏品,而是其他一些表格类型。我只是不确定。这就是我想要完成的。

我正在建立一个保险注册API。我正在尝试让symfony接受以下JSON

{
  "quote":{
    "birth_date":"1987/09/04",
    "zip_code": "90210",
    "effective_date":"2016-01-15",
    "coverage": "3",
    "plans": [
        {
            "carrier": "SOMEGUY",
            "deductible": "50",
            "enrollment_fee": "25.00",
            "id": "1234",
            "max_benefit": "1200",
            "name": "PPO 1234",
            "network": true,
            "ortho": true,
            "ppo": true,
            "type": "DEN",
            "vision": false,
            "program_number": "123456",
            "area_factor": "7",
            "rates": [
                {
                    "tier": "1",
                    "rate": "29.49"
                },
                {
                    "tier": "2",
                    "rate": "58.97"
                },
                {
                    "tier": "3",
                    "rate": "94.35"
                }
            ],
            "state": "CA"
        }
      ],
    "account": {
        "first_name": "Joe",
        "middle_initial": "T",
        "last_name": "Plumber",
        "address1": "123 Plumber St",
        "city": "Beverly Hills",
        "state": "CA",
        "zip_code": "90210",
        "home_phone": "555-233-1234",
        "work_phone": "555-233-1234",
        "email": "joetheplumber@pipes.com",
        "gender": "M",
        "birth_date": "1987-09-04",
        "marital_status": "M",
        "dependents": [
            {
                "first_name": "Mario",
                "last_name": "Plumber",
                "birth_date": "2011-02-16",
                "gender": "M",
                "type": "CH"
            },
            {
                "first_name": "Luigi",
                "last_name": "Plumber",
                "birth_date": "2012-05-04",
                "gender": "M",
                "type": "CH"
            },
            {
                "first_name": "Daisy",
                "last_name": "Plumber",
                "birth_date": "1987-08-03",
                "gender": "F",
                "type": "SP"
            }
        ],
        "credit_card": {
            "account_number": "1111222233334444",
            "billing_frequency": "M",
            "card_type": "V",
            "expiration": "01/2018"
        }
    }
  }
}

到目前为止,我的表单适用于plans部分。这是有道理的,它是一个数组形式的实际集合。但我不希望accountcredit_card成为数组。他们应该永远只是一个单一的实体。我认为问题源于收集总是想要接受一个数组。那么有更好的表单字段选项吗?

我正在使用FOSRestBundle和JMSSerializer。这里是我的表单类型的参考。

<?php

namespace DB\Bundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use DB\Bundle\Form\Type\PlanType;
use DB\Bundle\Form\Type\AccountType;

class EnrollType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('zipCode' , 'text' , array(
                'label' => 'Zip Code'))
            ->add('birthDate' , 'date' , array(
                'widget' => 'single_text',
                'format' => 'yyyy-MM-dd',
                'label' => 'Date of Birth', 
                'input' => 'datetime'))
            ->add('effectiveDate' , 'date' , array(
                'widget' => 'single_text',
                'format' => 'yyyy-MM-dd',
                'label' => 'Effective Date', 
                'input' => 'datetime'))
            ->add('coverage', 'choice', array(
                'choices' => array(1 => 'Individual', 2 => 'Individual and Spouse', 3 => 'Individual, Spouse, and Child(ren)', 5 => 'Individual and Children', 6 => 'Individual and Child'),
                'label' => 'Coverage',
            ))
            ->add('plans' , 'collection', array(
                'type' => new PlanType(),
                'by_reference' => false,
                'allow_add' => true
            ))
            ->add('account', 'collection', array(
                'type' => new AccountType(),
                'by_reference' => false,
                'allow_add' => true
            ));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'DB\Bundle\Entity\Quote',
        ));
    }

    public function getName()
    {
        return 'quote';
    }
}

namespace DB\Bundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use DB\Bundle\Form\Type\RatesType;

class PlanType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('carrier' , 'text' , array(
                'label' => 'Carrier'))
            ->add('deductible' , 'text' , array(
                'label' => 'Deductible'))
            ->add('enrollmentFee' , 'text' , array(
                'label' => 'Enrollment Fee'))
            ->add('id' , 'text' , array(
                'label' => 'Plan ID'))
            ->add('maxBenefit' , 'text' , array(
                'label' => 'Max Benefit'))
            ->add('name' , 'text' , array(
                'label' => 'Plan Name'))
            ->add('network' , 'text' , array(
                'label' => 'Network Prefered'))
            ->add('ortho' , 'text' , array(
                'label' => 'Ortho Coverage'))
            ->add('ppo' , 'text' , array(
                'label' => 'PPO'))
            ->add('rate' , 'text' , array(
                'label' => 'Rate'))
            ->add('type' , 'text' , array(
                'label' => 'Plan Type'))
            ->add('vision' , 'text' , array(
                'label' => 'Vision Plan'))
            ->add('deductible' , 'text' , array(
                'label' => 'Deductible'))
            ->add('programNumber' , 'text' , array(
                'label' => 'Program Number'))
            ->add('areaFactor' , 'text' , array(
                'label' => 'Area Factor'))
            ->add('state' , 'text' , array(
                'label' => 'State'))
            ->add('rates' , 'collection', array(
                'type' => new RatesType(),
                'by_reference' => false,
                'allow_add' => true
            ));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'DB\Bundle\Entity\Plan',
        ));
    }

    public function getName()
    {
        return 'plans';
    }
}

namespace DB\Bundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class RatesType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('tier' , 'text' , array(
                'label' => 'Tier'))
            ->add('rate' , 'text' , array(
                'label' => 'Rate'));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array());
    }

    public function getName()
    {
        return 'rates';
    }
}

namespace DB\Bundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use DB\Bundle\Form\Type\CreditCardType;
use DB\Bundle\Form\Type\EBTType;
use DB\Bundle\Form\Type\DependentType;

class AccountType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('firstName' , 'text' , array(
                'label' => 'First Name'))
            ->add('middleInitial' , 'text' , array(
                'label' => 'Middle Initial'))
            ->add('lastName' , 'text' , array(
                'label' => 'Last Name'))
            ->add('address1' , 'text' , array(
                'label' => 'Address Line 1'))
            ->add('address2' , 'text' , array(
                'label' => 'Address Line 2',
                'required' => false))
            ->add('city' , 'text' , array(
                'label' => 'City'))
            ->add('state' , 'text' , array(
                'label' => 'State'))
            ->add('zipCode' , 'text' , array(
                'label' => 'Ortho Coverage'))
            ->add('homePhone' , 'text' , array(
                'label' => 'Home Phone'))
            ->add('workPhone' , 'text' , array(
                'label' => 'Work Phone'))
            ->add('email' , 'email' , array(
                'label' => 'Email'))
            ->add('gender' , 'choice' , array(
                'choices' => array('M' => 'Male', 'F' => 'Female'),
                'label' => 'Gender'))
            ->add('birthDate' , 'date' , array(
                'widget' => 'single_text',
                'format' => 'yyyy-MM-dd',
                'label' => 'Date of Birth', 
                'input' => 'datetime'))
            ->add('maritalStatus' , 'choice' , array(
                'choices' => array('S' => 'Single', 'M' => 'Married', 'D' => 'Divorced', 'W' => 'Widowed'),
                'label' => 'Marital Status'))
            ->add('creditCard' , 'collection', array(
                'type' => new CreditCardType(),
                'required' => false,
                'by_reference' => false,
                'allow_add' => true
            ))
            ->add('ebt' , 'collection', array(
                'type' => new EBTType(),
                'required' => false,
                'by_reference' => false,
                'allow_add' => true
            ))
            ->add('dependents' , 'collection', array(
                'type' => new DependentType(),
                'required' => false,
                'by_reference' => false,
                'allow_add' => true
            ));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'DB\Bundle\Entity\Account',
        ));
    }

    public function getName()
    {
        return 'account';
    }
}

namespace DB\Bundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CreditCardType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('accountNumber' , 'text' , array(
                'label' => 'Card Number'))
            ->add('billingFrequency' , 'choice' , array(
                'choices' => array('M' => 'Monthly'),
                'label' => 'Billing Frequency'))
            ->add('cardType' , 'choice' , array(
                'choices' => array('V' => 'Visa', 'M' => 'MasterCard', 'D' => 'Discover'),
                'label' => 'Card Type'))
            ->add('expiration' , 'date' , array(
                'widget' => 'single_text',
                'format' => 'MM-yyyy d',
                'years' => range(date('Y'), date('Y')+12),
                'days' => array(1),
                'label' => 'Expiration Date', 
                'input' => 'datetime'));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'DB\Bundle\Entity\CreditCard',
        ));
    }

    public function getName()
    {
        return 'ceditCard';
    }
}

namespace DB\Bundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class DependentType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('firstName' , 'text' , array(
                'label' => 'First Name'))
            ->add('lastName' , 'text' , array(
                'label' => 'Last Name'))
            ->add('birthDate' , 'date' , array(
                'widget' => 'single_text',
                'format' => 'yyyy-MM-dd',
                'label' => 'Date of Birth', 
                'input' => 'datetime'))
            ->add('gender' , 'choice' , array(
                'choices' => array('M' => 'Male', 'F' => 'Female'),
                'label' => 'Gender'))
            ->add('type' , 'choice' , array(
                'choices' => array('CH' => 'Child', 'SP' => 'Spouse'),
                'label' => 'Dependent Type'));
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'DB\Bundle\Entity\Dependent',
        ));
    }

    public function getName()
    {
        return 'dependents';
    }
}

1 个答案:

答案 0 :(得分:4)

您可以将类型设置为add方法的第二个参数。

class EnrollType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // ... all your form fields ...
        $builder->add('account', new AccountType());
    }
}

这将嵌套您的另一种形式。有关方法签名,请参阅此处http://api.symfony.com/2.5/Symfony/Component/Form/FormBuilder.html#method_add