多对一关系:表单验证不会在数据库中创建外键

时间:2013-11-04 13:25:44

标签: forms symfony one-to-many many-to-one bidirectional

我在PostCategory和&之间有多对一的关系。 SubCategory是这样的:

SubCategory实体:

namespace VisualImmersion\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;

/**
 * SubCategory
 *
 * @ORM\Table(name="post_category_subcategory")
 * @ORM\Entity(repositoryClass="VisualImmersion\AdminBundle\Entity\Repository\SubCategoryRepository")
 */
class SubCategory
{
    /**
     * @var integer
     *
     * @ORM\Column(name="ID", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    /**
     * @ORM\ManyToOne(targetEntity="\VisualImmersion\AdminBundle\Entity\PostCategory", cascade={"remove", "persist"}, inversedBy="subCategories")
     * @ORM\JoinColumn(referencedColumnName="ID")
     */
    private $postCategory;


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

    /**
     * Set name
     *
     * @param string $name
     * @return SubCategory
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * Set category
     *
     * @param \VisualImmersion\AdminBundle\Entity\PostCategory $category
     */
    public function setPostCategory(\VisualImmersion\AdminBundle\Entity\PostCategory $category)
    {
        $this->postCategory = $category;
    }

    /**
     * Get category
     *
     * @return \VisualImmersion\AdminBundle\Entity\PostCategory
     */
    public function getPostCategory()
    {
        return $this->postCategory;
    }
}

PostCategory实体:

<?php

namespace VisualImmersion\AdminBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * PostCategory
 *
 * @ORM\Table(name="post_category")
 * @ORM\Entity(repositoryClass="VisualImmersion\AdminBundle\Entity\Repository\PostCategoryRepository")
 */
class PostCategory
{
    /**
     * @var integer
     *
     * @ORM\Column(name="ID", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=45, nullable=false)
     */
    private $name;

    /**
     * @ORM\ManyToMany(targetEntity="Post", mappedBy="posts")
     */
    private $posts;

    /**
     * @ORM\OneToMany(targetEntity="SubCategory", mappedBy="postCategory", cascade={"remove", "persist"})
     */
    protected $subCategories;


    public function __construct()
    {
        $this->posts = new \Doctrine\Common\Collections\ArrayCollection();
        $this->subCategories = new \Doctrine\Common\Collections\ArrayCollection();
    }

    public function __toString()
    {
        return (String) $this->id;
    }

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

    /**
     * Set name
     *
     * @param string $name
     * @return PostCategory
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * Add post
     *
     * @param \VisualImmersion\AdminBundle\Entity\Post $post
     */
    public function addPost(\VisualImmersion\AdminBundle\Entity\Post $post)
    {
        $this->posts[] = $post;
    }

    /**
     * Get posts
     *
     * @return \Doctrine\Common\Collections\ArrayCollection()
     */
    public function getPosts()
    {
        return $this->posts->toArray();
    }

    /**
     * Remove post
     *
     * @param \VisualImmersion\AdminBundle\Entity\Post $post
     */
    public function removePost(\VisualImmersion\AdminBundle\Entity\Post $post)
    {
        $this->posts->removeElement($post);
    }


    /**
     * Add subCategory
     *
     * @param \VisualImmersion\AdminBundle\Entity\SubCategory $subCategory
     */
    public function addSubCategory(\VisualImmersion\AdminBundle\Entity\SubCategory $subCategory)
    {
        $this->subCategories[] = $subCategory;
        $subCategory->setPostCategory($this);
    }

    /**
     * Get subCategories
     *
     * @return \Doctrine\Common\Collections\ArrayCollection()
     */
    public function getSubCategories()
    {
        return $this->subCategories;
    }

    /**
     * Set subCategories
     *
     * @param \Doctrine\Common\Collections\ArrayCollection $subCategories
     */
    public function setSubCategories(\Doctrine\Common\Collections\ArrayCollection $subCategories)
    {
        foreach ($subCategories as $subCategory) {
             $subCategory->setPostCategory($this);
        }

        $this->subCategories = $subCategories;
    }

    /**
     * Remove subCategory
     *
     * @param \VisualImmersion\AdminBundle\Entity\SubCategory $subCategory
     */
    public function removeSubCategory(\VisualImmersion\AdminBundle\Entity\SubCategory $subCategory)
    {
        $this->subCategories->removeElement($subCategory);
    }
}

我在PostCategory表单中嵌入了用于添加SubCategories集合的表单:

SubCategoryType:

<?php

namespace VisualImmersion\AdminBundle\Form;

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

class SubCategoryType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')

        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'VisualImmersion\AdminBundle\Entity\SubCategory'
        ));
    }

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

PostCategoryType:

<?php

namespace VisualImmersion\AdminBundle\Form;

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

class PostCategoryType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('subCategories', 'collection', array(
                'type' => new SubCategoryType(),
                'required' =>false,
                'allow_add' => true,
                'allow_delete' => true,
                'prototype' => true,
                'prototype_name' =>'subCategory__name__',
                'by_reference' => 'false'
            ));
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'VisualImmersion\AdminBundle\Entity\PostCategory'
        ));
    }

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

我的问题是在数据库的subCategory表中,没有添加postCategory外键:

我拼命想找到解决这个问题的方法,所以我请求你的帮助。

编辑:

我的控制器: PostCategory

<?php

namespace VisualImmersion\AdminBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use VisualImmersion\AdminBundle\Entity\PostCategory;
use VisualImmersion\AdminBundle\Form\PostCategoryType;

/**
 * PostCategory controller.
 *
 * @Route("/postcategory")
 */
class PostCategoryController extends Controller
{

    /**
     * Lists all PostCategory entities.
     *
     * @Route("/", name="postcategory")
     * @Method("GET")
     * @Template()
     */
    public function indexAction()
    {
        $em = $this->getDoctrine()->getManager();

        $entities = $em->getRepository('VisualImmersionAdminBundle:PostCategory')->findAll();

        return array(
            'entities' => $entities,
        );
    }
    /**
     * Creates a new PostCategory entity.
     *
     * @Route("/create", name="postcategory_create")
     * @Method("POST")
     * @Template("VisualImmersionAdminBundle:PostCategory:new.html.twig")
     */
    public function createAction(Request $request)
    {
        $entity  = new PostCategory();
        $form = $this->createForm(new PostCategoryType(), $entity);
        $form->submit($request);


        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl('postcategory_index', array('id' => $entity->getId())));
        }

        return array(
            'entity' => $entity,
            'form'   => $form->createView(),
        );
    }

    /**
     * Displays a form to create a new PostCategory entity.
     *
     * @Route("/new", name="postcategory_new")
     * @Method("GET")
     * @Template()
     */
    public function newAction()
    {
        $entity = new PostCategory();
        $form   = $this->createForm(new PostCategoryType(), $entity);

        return array(
            'entity' => $entity,
            'form'   => $form->createView(),
        );
    }

    /**
     * Finds and displays a PostCategory entity.
     *
     * @Route("/{id}", name="postcategory_show")
     * @Method("GET")
     * @Template()
     */
    public function showAction($id)
    {
        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('VisualImmersionAdminBundle:PostCategory')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find PostCategory entity.');
        }

        $deleteForm = $this->createDeleteForm($id);

        return array(
            'entity'      => $entity,
            'delete_form' => $deleteForm->createView(),
        );
    }

    /**
     * Displays a form to edit an existing PostCategory entity.
     *
     * @Route("/edit/{id}", name="postcategory_edit")
     * @Method("GET")
     * @Template()
     */
    public function editAction($id)
    {


        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('VisualImmersionAdminBundle:PostCategory')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find PostCategory entity.');
        }

        $editForm = $this->createForm(new PostCategoryType(), $entity);
        $deleteForm = $this->createDeleteForm($id);

        return array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        );
    }

    /**
     * Edits an existing PostCategory entity.
     *
     * @Route("/update/{id}", name="postcategory_update")
     * @Method("PUT")
     * @Template("VisualImmersionAdminBundle:PostCategory:edit.html.twig")
     */
    public function updateAction(Request $request, $id)
    {

        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('VisualImmersionAdminBundle:PostCategory')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find PostCategory entity.');
        }

        $deleteForm = $this->createDeleteForm($id);
        $editForm = $this->createForm(new PostCategoryType(), $entity);

        $editForm->submit($request);
        if ($editForm->isValid()) {

            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl('postcategory_edit', array('id' => $id)));
        }

        return array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        );
    }
    /**
     * Deletes a PostCategory entity.
     *
     * @Route("/delete/{id}", name="postcategory_delete")
     * @Method("DELETE")
     */
    public function deleteAction(Request $request, $id)
    {
        $form = $this->createDeleteForm($id);
        $form->submit($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $entity = $em->getRepository('VisualImmersionAdminBundle:PostCategory')->find($id);

            if (!$entity) {
                throw $this->createNotFoundException('Unable to find PostCategory entity.');
            }

            $em->remove($entity);
            $em->flush();
        }

        return $this->redirect($this->generateUrl('postcategory_index'));
    }

    /**
     * Creates a form to delete a PostCategory entity by id.
     *
     * @param mixed $id The entity id
     *
     * @return \Symfony\Component\Form\Form The form
     */
    private function createDeleteForm($id)
    {
        return $this->createFormBuilder(array('id' => $id))
            ->add('id', 'hidden')
            ->getForm()
        ;
    }
}

子类别:

<?php

namespace VisualImmersion\AdminBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use VisualImmersion\AdminBundle\Entity\SubCategory;
use VisualImmersion\AdminBundle\Form\SubCategoryType;

/**
 * SubCategory controller.
 *
 * @Route("/subcategory")
 */
class SubCategoryController extends Controller
{

    /**
     * Lists all SubCategory entities.
     *
     * @Route("/", name="subcategory")
     * @Method("GET")
     * @Template()
     */
    public function indexAction()
    {
        $em = $this->getDoctrine()->getManager();

        $entities = $em->getRepository('VisualImmersionAdminBundle:SubCategory')->findAll();

        return array(
            'entities' => $entities,
        );
    }
    /**
     * Creates a new SubCategory entity.
     *
     * @Route("/", name="subcategory_create")
     * @Method("POST")
     * @Template("VisualImmersionAdminBundle:SubCategory:new.html.twig")
     */
    public function createAction(Request $request)
    {
        $entity  = new SubCategory();
        $form = $this->createForm(new SubCategoryType(), $entity);
        $form->submit($request);

        $logger = $this->get('logger');
        $logger->info('Nous sommes dans le Create Action de SubCategory');

        if ($form->isValid()) {
            $logger->info('Le formulaire semble valide dans le Create Action de SubCategory');
            $em = $this->getDoctrine()->getManager();
            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl('subcategory_show', array('id' => $entity->getId())));
        }

        return array(
            'entity' => $entity,
            'form'   => $form->createView(),
        );
    }

    /**
     * Displays a form to create a new SubCategory entity.
     *
     * @Route("/new", name="subcategory_new")
     * @Method("GET")
     * @Template()
     */
    public function newAction()
    {
        $logger = $this->get('logger');
        $logger->info('Nous sommes dans le New Action de SubCategory');
        $entity = new SubCategory();
        $form   = $this->createForm(new SubCategoryType(), $entity);

        return array(
            'entity' => $entity,
            'form'   => $form->createView(),
        );
    }

    /**
     * Finds and displays a SubCategory entity.
     *
     * @Route("/{id}", name="subcategory_show")
     * @Method("GET")
     * @Template()
     */
    public function showAction($id)
    {
        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('VisualImmersionAdminBundle:SubCategory')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find SubCategory entity.');
        }

        $deleteForm = $this->createDeleteForm($id);

        return array(
            'entity'      => $entity,
            'delete_form' => $deleteForm->createView(),
        );
    }

    /**
     * Displays a form to edit an existing SubCategory entity.
     *
     * @Route("/{id}/edit", name="subcategory_edit")
     * @Method("GET")
     * @Template()
     */
    public function editAction($id)
    {
        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('VisualImmersionAdminBundle:SubCategory')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find SubCategory entity.');
        }

        $editForm = $this->createForm(new SubCategoryType(), $entity);
        $deleteForm = $this->createDeleteForm($id);

        return array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        );
    }

    /**
     * Edits an existing SubCategory entity.
     *
     * @Route("/{id}", name="subcategory_update")
     * @Method("PUT")
     * @Template("VisualImmersionAdminBundle:SubCategory:edit.html.twig")
     */
    public function updateAction(Request $request, $id)
    {
        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('VisualImmersionAdminBundle:SubCategory')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find SubCategory entity.');
        }

        $deleteForm = $this->createDeleteForm($id);
        $editForm = $this->createForm(new SubCategoryType(), $entity);
        $editForm->submit($request);

        if ($editForm->isValid()) {
            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl('subcategory_edit', array('id' => $id)));
        }

        return array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        );
    }
    /**
     * Deletes a SubCategory entity.
     *
     * @Route("/{id}", name="subcategory_delete")
     * @Method("DELETE")
     */
    public function deleteAction(Request $request, $id)
    {
        $form = $this->createDeleteForm($id);
        $form->submit($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $entity = $em->getRepository('VisualImmersionAdminBundle:SubCategory')->find($id);

            if (!$entity) {
                throw $this->createNotFoundException('Unable to find SubCategory entity.');
            }

            $em->remove($entity);
            $em->flush();
        }

        return $this->redirect($this->generateUrl('subcategory'));
    }

    /**
     * Creates a form to delete a SubCategory entity by id.
     *
     * @param mixed $id The entity id
     *
     * @return \Symfony\Component\Form\Form The form
     */
    private function createDeleteForm($id)
    {
        return $this->createFormBuilder(array('id' => $id))
            ->add('id', 'hidden')
            ->getForm()
        ;
    }
}

3 个答案:

答案 0 :(得分:0)

我想我认为这可能是问题所在。

您有以下@ManyToOne关系:

/**
 * @ORM\ManyToOne(targetEntity="\VisualImmersion\AdminBundle\Entity\PostCategory", cascade={"remove", "persist"}, inversedBy="subCategories")
 * @ORM\JoinColumn(referencedColumnName="ID")
 */
private $postCategory;

...但是关系的任何一方都不知道该外键列的名称是什么。尝试以这种方式改变它:

@ORM\JoinColumn(name="postCategory_id", referencedColumnName="ID")

答案 1 :(得分:0)

为什么不尝试使用ORM创建实体? 这对于创建数据库也很有帮助。

答案 2 :(得分:0)

我找到了解决方案:

/**
     * Edits an existing PostCategory entity.
     *
     * @Route("/update/{id}", name="postcategory_update")
     * @Method("PUT")
     * @Template("VisualImmersionAdminBundle:PostCategory:edit.html.twig")
     */
    public function updateAction(Request $request, $id)
    {

        $em = $this->getDoctrine()->getManager();

        $entity = $em->getRepository('VisualImmersionAdminBundle:PostCategory')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find PostCategory entity.');
        }

        $deleteForm = $this->createDeleteForm($id);
        $editForm = $this->createForm(new PostCategoryType(), $entity);

        $editForm->submit($request);
        if ($editForm->isValid()) {
            foreach ($entity->getSubCategories() as $subCategory)
            {
                $subCategory->setPostCategory($entity);
                $em->persist($subCategory);
            }
            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl('postcategory_edit', array('id' => $id)));
        }

        return array(
            'entity'      => $entity,
            'edit_form'   => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        );
    }

我不确定这是最好的解决方案。必须实际更改控制器。我本来希望只为这些东西修改实体。你有更好的主意吗?