Symfony2表单映射问题

时间:2014-09-12 19:47:57

标签: php forms symfony

我在提交实体后遇到数据映射问题

实体:

<?php

namespace Site\UserBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\EntityManager;
use JMS\Serializer\Annotation as Serializer;
use JMS\Serializer\Annotation\Groups;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection; 

/**
 * UserAddress
 *
 * @ORM\Table(name="user_address")
 * @ORM\Entity
 * 
 * @Serializer\ExclusionPolicy("all")
 * ---------- SERIALIZER GROUPS -----
 * all -- All entries
 */
class UserAddress
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * 
     * @Serializer\Type("integer")
     * @Serializer\Expose
     * @serializer\SerializedName("ID")
     * @serializer\Groups({"all"})
     */
    public $ID;

    /**
     * @var integer
     *
     * @ORM\Column(name="user_id", type="integer", nullable=false)
     */
    public $UserId;

     /**
     * @var integer
     *
     * @ORM\Column(name="level_id", type="integer", nullable=false)
     * 
     * @Serializer\Type("integer")
     * @Serializer\Expose
     * @serializer\SerializedName("LevelId")
     * @serializer\Groups({"all"})
     */
    public $LevelId;

     /**
     * @var integer
     *
     * @ORM\Column(name="address_type_id", type="integer", nullable=false)
     * 
     * @Serializer\Type("integer")
     * @Serializer\Expose
     * @serializer\SerializedName("AddressTypeId")
     * @serializer\Groups({"all"})
     * 
     * @Assert\NotBlank()
     */
    public $AddressTypeId;

    /**
     * @var string
     *
     * @ORM\Column(name="address_data", type="text", nullable=false)
     * 
     * @Serializer\Type("string")
     * @Serializer\Expose
     * @serializer\SerializedName("Address Data")
     * @serializer\Groups({"all"})
     * 
     * @Assert\NotBlank()
     */
    public $AddressData;

    /**
     * @var integer
     *
     * @ORM\Column(name="public_yn", type="integer", nullable=false)
     * 
     * @Serializer\Type("boolean")
     * @Serializer\Expose
     * @serializer\SerializedName("PublicYN")
     * @serializer\Groups({"all"})
     * 
     * @Assert\NotBlank()
     */
    public $PublicYN;

    /**
     * @var integer
     *
     * @ORM\Column(name="primary_yn", type="integer", nullable=false)
     * 
     * @Serializer\Type("boolean")
     * @Serializer\Expose
     * @serializer\SerializedName("PrimaryYN")
     * @serializer\Groups({"all"})
     * 
     * @Assert\NotBlank()
     */
    public $PrimaryYN;

     /**
    * @ORM\ManyToOne(targetEntity="Site\UserBundle\Entity\UserMain", inversedBy="UserAddress")
    * @ORM\JoinColumn(name="user_id", referencedColumnName="user_id")
    */
    public $User;  

    /**
     * @ORM\ManyToOne(targetEntity="Site\UserBundle\Entity\UserAddressType", inversedBy="UserAddress")
     * @ORM\JoinColumn(name="address_type_id", referencedColumnName="address_type_id")
     * 
     * @Serializer\Type("Site\UserBundle\Entity\UserAddressType")
     * @Serializer\Expose
     * @serializer\SerializedName("UserAddressType")
     * @serializer\Groups({"all"})
     */
     public $UserAddressType;




    /**
     * Get ID
     *
     * @return integer 
     */
    public function getID()
    {
        return $this->ID;
    }

    /**
     * Set UserId
     *
     * @param integer $userId
     * @return UserAddress
     */
    public function setUserId($userId)
    {
        $this->UserId = $userId;

        return $this;
    }

    /**
     * Get UserId
     *
     * @return integer 
     */
    public function getUserId()
    {
        return $this->UserId;
    }

    /**
     * Set LevelId
     *
     * @param integer $levelId
     * @return UserAddress
     */
    public function setLevelId($levelId)
    {
        $this->LevelId = $levelId;

        return $this;
    }

    /**
     * Get LevelId
     *
     * @return integer 
     */
    public function getLevelId()
    {
        return $this->LevelId;
    }

    /**
     * Set AddressTypeId
     *
     * @param integer $addressTypeId
     * @return UserAddress
     */
    public function setAddressTypeId($addressTypeId)
    {
        $this->AddressTypeId = $addressTypeId;

        return $this;
    }

    /**
     * Get AddressTypeId
     *
     * @return integer 
     */
    public function getAddressTypeId()
    {
        return $this->AddressTypeId;
    }

    /**
     * Set AddressData
     *
     * @param string $addressData
     * @return UserAddress
     */
    public function setAddressData($addressData)
    {
        $this->AddressData = $addressData;

        return $this;
    }

    /**
     * Get AddressData
     *
     * @return string 
     */
    public function getAddressData()
    {
        return $this->AddressData;
    }

    /**
     * Set PublicYN
     *
     * @param integer $publicYN
     * @return UserAddress
     */
    public function setPublicYN($publicYN)
    {
        $this->PublicYN = $publicYN;

        return $this;
    }

    /**
     * Get PublicYN
     *
     * @return integer 
     */
    public function getPublicYN()
    {
        return $this->PublicYN;
    }

    /**
     * Set PrimaryYN
     *
     * @param integer $primaryYN
     * @return UserAddress
     */
    public function setPrimaryYN($primaryYN)
    {
        $this->PrimaryYN = $primaryYN;

        return $this;
    }

    /**
     * Get PrimaryYN
     *
     * @return integer 
     */
    public function getPrimaryYN()
    {
        return $this->PrimaryYN;
    }

    /**
     * Set User
     *
     * @param \Site\UserBundle\Entity\UserMain $user
     * @return UserAddress
     */
    public function setUser(\Site\UserBundle\Entity\UserMain $user = null)
    {
        $this->User = $user;

        return $this;
    }

    /**
     * Get User
     *
     * @return \Site\UserBundle\Entity\UserMain 
     */
    public function getUser()
    {
        return $this->User;
    }

    /**
     * Set UserAddressType
     *
     * @param \Site\UserBundle\Entity\UserAddressType $userAddressType
     * @return UserAddress
     */
    public function setUserAddressType(\Site\UserBundle\Entity\UserAddressType $userAddressType = null)
    {
        $this->UserAddressType = $userAddressType;

        return $this;
    }

    /**
     * Get UserAddressType
     *
     * @return \Site\UserBundle\Entity\UserAddressType 
     */
    public function getUserAddressType()
    {
        return $this->UserAddressType;
    }
}

表格是:

namespace Site\UserBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\ORM\EntityRepository;

class UserAddressType extends AbstractType
{
        /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('UserId','hidden')
            ->add('LevelId', 'integer', array(
                    'label'=>'Sort Rate (Order)'
                ))
            ->add('AddressTypeId', 'entity', array(
                    'class'=>'SiteUserBundle:UserAddressType',
                    'query_builder'=> function(EntityRepository $er){
                            return $er->createQueryBuilder('t')
                            ->orderBy('t.AddressDescription', 'ASC');                        
                        },
                    'property'=>'AddressDescription',
                    'label'=>'Address Type'
                ))
            ->add('AddressData', 'text')
            ->add('PublicYN', 'choice', array(
                    'choices' => array( 'false'=>'Private', 'true'=>'Public'),
                    'required'=>true,
                    'label'=>'Pubicly Visable'
                ))
            ->add('PrimaryYN', 'choice', array(
                    'choices' => array( 'false'=>'Secondary', 'true'=>'Primary'),
                    'required'=>true,
                    'label'=>'Primary Contact',
                ))
            ->add('save', 'submit', array(
                        'label'=>'Add Address',
                        'attr'=>array(
                            'class'=>'btn btn-primary',
                        ),
                  ))
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Site\UserBundle\Entity\UserAddress',
            'csrf_protection'=>false,
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'Create_User_Address';
    }
}

控制器功能是:(我正在使用fosrestbundle)

public function newAddressAction($userid, Request $request)
    {

        $statusCode = 201;
        $address = new UserAddress();
        $address->setUserId($userid);

        $form = $this->createForm( new UserAddressType(), $address, array(
                'method'=>'GET',
            ));
        $form->handleRequest($request);

        if($form->isValid()){
               $em = $this->getDoctrine()->getManager();
               $em->persist($address);
               $em->flush();
               return new Response('User Added to system');
        }        
        return $this->render('SiteUserBundle:UserAddress:newUserAddress.html.twig', array(
            'form' => $form->createView(),

));     }

Twig模板非常简单。所有数据都正确发布到服务器:(查询字符串参数)

Create_User_Address[LevelId]:0
Create_User_Address[AddressTypeId]:5
Create_User_Address[AddressData]:555-555-5555
Create_User_Address[PublicYN]:false
Create_User_Address[PrimaryYN]:false
Create_User_Address[save]:
Create_User_Address[UserId]:3

但我一直收到以下错误:

An exception occurred while executing 'INSERT INTO user_address (user_id, level_id, address_type_id, address_data, public_yn, primary_yn) VALUES (?, ?, ?, ?, ?, ?)' with params [null, 0, null, "555-555-5555", "false", "false"]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user_id' cannot be null

如您所见,UserID和AddressTypeId字段未从表单映射到实体。我查看了所有3件以上和ove的代码,对于我的生活,我无法看到不匹配发生的地方。我曾在某一点更改了Entity中这两个字段的名称,但我删除了所有getter和setter并重新生成它们以及清除dev缓存。

我的预感是Symfony2中有一个文件有一个映射类错了,但我找不到它..

全部谢谢

编辑:

我尝试清除这里所述的学说缓存:Symfony2 doctrine clear cache

app/console doctrine:cache:clear-metadata 
app/console doctrine:cache:clear-query  
app/console doctrine:cache:clear-result

这会导致生成相同的错误,因此缓存问题可能不在桌面上。

编辑:

根据艾萨克的建议,我删除了->add('UserId', 'hidden')。表单仍然贴有相同的错误消息。正在为页面正确生成该字段; <input type="hidden" id="Create_User_Address_UserId" name="Create_User_Address[UserId]" class=" form-control" value="3"> 正如您可以从上面的查询参数中看到的那样正确地发回服务器。

编辑:

我将问题跟踪到UserUserAddressType变量。如果我删除这两个变量及其getter和setter,则表单可以完美运行而无需对我的代码进行其他修改。我应该注意到这两个变量是与其他实体的连接。他们似乎正在消除表格提交的数据。

2 个答案:

答案 0 :(得分:0)

删除

->add('UserId','hidden')

它可能用null覆盖UserId,因为它是隐藏的并且没有值

答案 1 :(得分:0)

根据lsouza的建议,我必须创建一个data transformer

namespace Site\UserBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;

use Site\UserBundle\Entity\UserAddressType;

class AddressTypeToNumber implements DataTransformerInterface
{
    /**
     * @var ObjectManager
     */
    private $om;

    /**
     * @param ObjectManager $om
     */
    public function __construct(ObjectManager $om)
    {
        $this->om = $om;
    }

    /**
     * Transforms an object(val) to a string
     * 
     * @param UserAddressType|null $val
     * @return string
     */
    public function transform($val)
    {
        if (null === $val) {
            return "";
        }

        return array();
    }

    /**
     * Transfers a string to an object (UserAddressType)
     * 
     * @param string $val
     * @return UserAddressType|null 
     * @throws TransformationFailedException if object is not found
     */
    public function reverseTransform($val)
    {
        if (!$val) {
            return null;
        }

        $addId = $this->om
            ->getRepository('SiteUserBundle:UserAddressType')
            ->findOneBy(array('AddressTypeId' => $val));  

         if (null === $addId) {
             throw new TransformationFailedException(sprintf(
                'An Address Type with the ID of "%s" does not exsist in the system',
                $val
             ));
         }

        return $addId;
    }
}

请注意,Transformer函数当前返回null,但这应返回表单可以使用的值。

其他一些可能对其他人有帮助的注意事项是表单类也需要更改。

setDefaultOptions函数需要在$resolver变量中添加以下内容:

    ->setRequired(array(
        'em',
    ))
    ->setAllowedTypes(array(
        'em'=>'Doctrine\Common\Persistence\ObjectManager',
    ));

buildForm函数需要稍微更改才能接受em选项:

public function buildForm(FormBuilderInterface $builder, array $options)
{
   $em = $options['em'];
   $transformer = new AddressTypeToNumber($em);

该字段需要更改为包含实体中关系的varrable,而不是链接中使用的字段:

    ->add(
        $builder->create('UserAddressType', 'entity', array(
            'class' => 'SiteUserBundle:UserAddressType',
            'property' => 'AddressDescription',
            'label' => 'Address Type'
        ))
        ->addModelTransformer($transformer)
    )

最后在您的控制器中,您需要将$this->getDoctrine()->getManager()的实例传递给表单类:

$form = $this->createForm( new UserAddressType(), $address, array(
    'em' => $this->getDoctrine()->getManager(),
));

我希望这有助于其他人。