Symfony2 - Misd phonnumberbundle:无法转换属性路径“phone_number”的值:预期\ libphonenumber \ PhoneNumber

时间:2016-11-07 10:36:58

标签: symfony

下面是我的Entity,Form和DBAL配置,用于与Symfony2.8集成的misd-phonenumberbundle。但我仍然得到以下错误,有人能告诉我如何解决这个问题吗?我写了几行代码将字符串转换为PhoneNumber obj然后表单加载正常但我的问题是我们需要显式转换它吗?这不是自动处理的吗?

实体条目:

/**
* @ORM\Column(type="phone_number", nullable=true)
* @AssertPhoneNumber(defaultRegion="US", message="Please specify a valid phone number")
*/
private $phoneNumber;

DBAL映射:

doctrine:
dbal:
types:
phone_number: Misd\PhoneNumberBundle\Doctrine\DBAL\Types\PhoneNumberType

形式:

->add('phoneNumber', PhoneNumberType::class, array('default_region' => 'US', 'format' => PhoneNumberFormat::NATIONAL, 'required' => false))

处理错误的自定义代码:

if($user->getphoneNumber()!="")
{
   $util = $this->container->get('libphonenumber.phone_number_util');
   $phoneNUmber = $util->parse($user->getphoneNumber(), "US");
   $user->setphoneNumber($phoneNUmber);
}
else
{
    $phoneNUmber = new \libphonenumber\PhoneNumber;
    $user->setphoneNumber($phoneNUmber);
}

Error:    
  

未捕获的PHP异常Symfony \ Component \ Form \ Exception \ TransformationFailedException:无法转换属性路径“phone_number”的值:在webapp / vendor / symfony / symfony / src / Symfony / Component / Form /中预期\ libphonenumber \ PhoneNumber Form.php第1149行

1 个答案:

答案 0 :(得分:3)

以下是我的解决方案。我没有在app / config.yml中做过任何学说映射

此解决方案假定MisdPhonenumber包已在AppKernel.php中注册

  1. 创建数据转换器:src / Example / Bundle / Form / DataTransformer.php
  2. Data Transformer Class

    <?php
    
    namespace Example\Bundle\Form\DataTransformer;
    
    use libphonenumber\PhoneNumber;
    use libphonenumber\PhoneNumberFormat;
    use Symfony\Component\Form\DataTransformerInterface;
    
    class StringToPhoneNumberTransformer implements DataTransformerInterface 
    {
    
        // The 'libphonenumber.phone_number_util' service 
        private $phoneNumberUtil; public function __construct($util)
        {
            $this->phoneNumberUtil = $util; 
        }
    
        /**
         * Transforms a string (number) to an object (PhoneNumber)
         *
         * @param  string $phoneNumberString
         * @return PhoneNumber
         */
        public function transform($phoneNumberString)
        {
            if ($phoneNumberString != "")
            {
                return $this->phoneNumberUtil->parse($phoneNumberString, "US");
            }
            return new PhoneNumber;
        }
    
        /**
         * Transforms a string (number) to an object (issue).
         *
         * @param  PhoneNumber $phoneNumberObject
         * @return string
         */
        public function reverseTransform($phoneNumberObject)
        {
            if ($phoneNumberObject != null)
            {
                return $this->phoneNumberUtil->format($phoneNumberObject, PhoneNumberFormat::NATIONAL);
            }
            return '';
        }
    }
    
    1. 使用表单中的数据转换器
    2. Data Transformer in Form

      <?php
      
      namespace Example\Bundle\Form\Type\User;
      
      use Example\Bundle\Entity\User;
      use Example\Bundle\Form\DataTransformer\StringToPhoneNumberTransformer;
      use Example\Bundle\Services\States;
      use libphonenumber\PhoneNumberFormat;
      use Misd\PhoneNumberBundle\Form\Type\PhoneNumberType;
      use Symfony\Component\Form\AbstractType;
      use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
      use Symfony\Component\Form\Extension\Core\Type\EmailType;
      use Symfony\Component\Form\Extension\Core\Type\SubmitType;
      use Symfony\Component\Form\Extension\Core\Type\TextType;
      use Symfony\Component\Form\FormBuilderInterface;
      use Symfony\Component\OptionsResolver\OptionsResolver;
      
      class ContactInfoType extends AbstractType
      {
          // The 'libphonenumber.phone_number_util' service private $phoneNumberUtil;
          public function __construct($util)
          {
              $this->phoneNumberUtil = $util;
          }
      
          public function buildForm(FormBuilderInterface $builder, array $options)
          {
              $builder->add('salutation', TextType::class, array('max_length' => 10, 'required' => false))
                  ->add('firstName', TextType::class, array('max_length' => 30))
                  ->add('lastName', TextType::class, array('max_length' => 30))
                  ->add('email', EmailType::class, array('max_length' => 150))
                  ->add('phone', PhoneNumberType::class,
                      array('default_region' => 'US', 'format' => PhoneNumberFormat::NATIONAL, 'required' => false))
                  ->add('stAddress1', TextType::class,
                      array('label' => 'Address Line 1', 'max_length' => 60, 'required' => false))
                  ->add('stAddress2', TextType::class,
                      array('label' => 'Address Line 2', 'max_length' => 60, 'required' => false))
                  ->add('city', TextType::class, array('max_length' => 30, 'required' => false))
                  ->add('state', ChoiceType::class,
                      array('choices' => States::getStates(), 'required' => false, 'choices_as_values' => true))
                  ->add('zip', TextType::class, array('max_length' => 5, 'required' => false))
                  ->add('submit', SubmitType::class);
      
              $builder->get('phone')->addModelTransformer(new StringToPhoneNumberTransformer($this->phoneNumberUtil));
          }
      
          public function getBlockPrefix()
          {
              return 'ContactInfo';
          }
      
          public function configureOptions(OptionsResolver $resolver){
              // Explicitly bind data class of form.
              $resolver->setDefaults([
                  'data_class' => User::class
              ]);
          }
      }
      
      1. 在配置文件中将表单类型定义为服务:
      2. Form type as a service

        # src/Example/Bundle/Resources/config/services.yml
        
        services:
            example.form.contactinfo:
                class: Example\Bundle\Form\Type\User\ContactInfoType
            arguments: ["@libphonenumber.phone_number_util"]
            tags:
                - { name: form.type }