Symfony如何创建一个实体并将其添加到另一个实体?

时间:2017-03-26 11:57:48

标签: symfony symfony-forms

嗨,谢谢你花时间阅读本文。 英语不是我的第一语言,所以我希望你能帮我找错。 目前我正在做一个熟悉Symfony 3的项目。

这就是我想要做的事情:

我有一个OneToMany关系,Game to PlayLog。 建立关系,我可以查看我的游戏中的日期列表。

我想创建一个新的PlayLog并与游戏相关联,这样我就可以通过游戏访问所有相关的PlayLog。 显示的视图带有游戏ID(log.html.twig)

我的问题: 如何使用表单和日期formField(dateType)创建一个新的PlayLog,并将其添加到现有游戏中?

更新:使用当前代码我现在收到此错误:

  

执行' INSERT INTO play_log时发生异常(日期,   game_id)VALUES(?,?)'与params [" 2017-03-04",null]:   SQLSTATE [23000]:完整性约束违规:1048列' game_id'   不能为空

这是我的代码:

--- entity / Game.php

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Game
 *
 * @ORM\Table(name="game")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\GameRepository")
 */
class Game
{

    /**
     * @ORM\OneToMany(targetEntity="PlayLog", mappedBy="game")
     */
    private $playlogs;
    public function __construct()
    {
        $this->playlogs = new ArrayCollection();
    }

    /**
     * @ORM\ManyToOne(targetEntity="Type", inversedBy="games")
     * @ORM\JoinColumn(name="type_id", referencedColumnName="id")
     */
    private $type;


    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;


    /**
     * @var string
     * @Assert\NotBlank()
     * @Assert\Length(
     *     min = "3",
     *  max = "100"
     * )
     * @ORM\Column(name="name", type="string", length=255, unique=true)
     */
    private $name;


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

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

        return $this;
    }

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

    /**
     * @return mixed
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * @ORM\Column (options={"default" = none})
     * @param mixed $type
     */
    public function setType($type)
    {
        $this->type = $type;
    }


    /**
     * @return mixed
     */
    public function getPlaylogs()
    {
        return $this->playlogs;
    }

    /**
     * @param mixed $playlogs
     */
    public function setPlaylogs($playlogs)
    {
        $this->playlogs = $playlogs;
    }

    public function addPlayLog(PlayLog $playlog)
    {
        $this->playlog->add($playlog);
        $playlog->setPlayLogs($this);
    }

}

--- entity / PlayLog.php

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * PlayLog
 *
 * @ORM\Table(name="play_log")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\PlayLogRepository")
 */
class PlayLog
{

    /**
     * @ORM\ManyToOne(targetEntity="Game", inversedBy="playlogs")
     * @ORM\JoinColumn(name="game_id", referencedColumnName="id")
     */
    private $game;


    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="date", type="date")
     */
    private $date;

    /**
     * @var int
     *
     * @ORM\Column(name="game_id", type="integer")
     */
    private $gameId;


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

    /**
     * Set date
     *
     * @param \DateTime $date
     *
     * @return PlayLog
     */
    public function setDate($date)
    {
        $this->date = $date;

        return $this;
    }

    /**
     * Get date
     *
     * @return \DateTime
     */
    public function getDate()
    {
        return $this->date;
    }

    /**
     * Set gameId
     *
     * @param integer $gameId
     *
     * @return PlayLog
     */
    public function setGameId($gameId)
    {
        $this->gameId = $gameId;

        return $this;
    }

    /**
     * Get gameId
     *
     * @return int
     */
    public function getGameId()
    {
        return $this->gameId;
    }


    public function addGame(Game $game)
    {
        $this->games->add($game);
        $game->setType($this);
    }
    public function removeGame(Game $game)
    {
        $this->games->removeElement($game);
    }



}

--- GameController.php

<?php

namespace AppBundle\Controller;

use AppBundle\Entity\Game;
use AppBundle\Entity\PlayLog;
use AppBundle\Entity\Type;
use AppBundle\Form\GameType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\HttpFoundation\Request;
/**
 * Game controller.
 *
 * @Route("game")
 */
class GameController extends Controller
{
    /**
     * Lists all game entities.
     *
     * @Route("/", name="game_index")
     * @Method("GET")
     */
    public function indexAction(Request $request)
    {
        $em = $this->getDoctrine()->getManager();
//        $games = $em->getRepository('AppBundle:Game')->findAll();
        $dql = "SELECT game FROM AppBundle:Game game JOIN game.type type ORDER BY game.name";
        $query = $em->createQuery($dql);
        /*
         * @var $paginator \Knp\Component\Pager\Paginator
         */
        $paginator = $this->get('knp_paginator');
        $result = $paginator->paginate(
             $query,
            $request->query->getInt('page', 1),
            $request->query->getInt('limit', 25)
        );
//        dump(get_class($paginator));

        return $this->render('game/index.html.twig', array(
            'games' => $result,
            'max_limit_error' => 25
        ));
    }

    /**
     * Creates a new game entity.
     *
     * @Route("/new", name="game_new")
     * @Method({"GET", "POST"})
     */
    public function newAction(Request $request)
    {

        $game = new Game();

        $form = $this->createForm('AppBundle\Form\GameType', $game);
        $form->handleRequest($request);

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

            return $this->redirectToRoute('game_show', array('id' => $game->getId()));
        }

        return $this->render('game/new.html.twig', array(
            'game' => $game,
            'form' => $form->createView(),
        ));
    }

    /**
     * Finds and displays a game entity.
     *
     * @Route("/{id}", name="game_show")
     * @Method("GET")
     */
    public function showAction(Game $game)
    {
        $deleteForm = $this->createDeleteForm($game);


        return $this->render('game/show.html.twig', array(
            'game' => $game,
            'delete_form' => $deleteForm->createView(),
        ));
    }

    /**
     * Displays a form to edit an existing game entity.
     *
     * @Route("/{id}/edit", name="game_edit")
     * @Method({"GET", "POST"})
     */
    public function editAction(Request $request, Game $game)
    {
        $deleteForm = $this->createDeleteForm($game);
        $editForm = $this->createForm('AppBundle\Form\GameType', $game);
        $editForm->handleRequest($request);

        if ($editForm->isSubmitted() && $editForm->isValid()) {
            $this->getDoctrine()->getManager()->flush();

            return $this->redirectToRoute('game_show', array('id' => $game->getId()));
        }

        return $this->render('game/edit.html.twig', array(
            'game' => $game,
            'edit_form' => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),

        ));
    }

    /**
     * Displays a form to edit an existing game entity.
     *
     * @Route("/{id}/log", name="game_log")
     * @Method({"GET", "POST"})
     */
    public function addLogAction(Request $request, Game $game)
    {
        $playlog = new PlayLog();
        $form = $this->createForm(GameType::class, $game);
        $form->handleRequest($request);
        if($form->isSubmitted() && $form->isValid()) {

            //Save playLog
            $em = $this->getDoctrine()->getManager();
            $em->persist($playlog);
            $em->flush();

        }
        // Render / return view incl. formulier.
        return $this->render('game/log.html.twig', array(
            'game' => $game,
            'form' => $form->createView(),
        ));
    }

    /**
     * Deletes a game entity.
     *
     * @Route("/{id}", name="game_delete")
     * @Method("DELETE")
     */
    public function deleteAction(Request $request, Game $game)
    {
        $form = $this->createDeleteForm($game);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->remove($game);
            $em->flush($game);
        }

        return $this->redirectToRoute('game_index');
    }

    /**
     * Creates a form to delete a game entity.
     *
     * @param Game $game The game entity
     *
     * @return \Symfony\Component\Form\Form The form
     */
    private function createDeleteForm(Game $game)
    {
        return $this->createFormBuilder()
            ->setAction($this->generateUrl('game_delete', array('id' => $game->getId())))
            ->setMethod('DELETE')
            ->getForm()
        ;
    }
}

--- PlayLogController.php

<?php

namespace AppBundle\Controller;

use AppBundle\Entity\PlayLog;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Symfony\Component\HttpFoundation\Request;

/**
 * Playlog controller.
 *
 * @Route("playlog")
 */
class PlayLogController extends Controller
{
    /**
     * Lists all playLog entities.
     *
     * @Route("/", name="playlog_index")
     * @Method("GET")
     */
    public function indexAction()
    {
        $em = $this->getDoctrine()->getManager();

        $playLogs = $em->getRepository('AppBundle:PlayLog')->findAll();

        return $this->render('playlog/index.html.twig', array(
            'playLogs' => $playLogs,
        ));
    }
   /**
     * Creates a new playLog entity.
     *
     * @Route("/{gameId}/new", name="playlog_new")
     * @Method({"GET", "POST"})
     */
    public function newAction(Request $request, $gameId)
    {

        $playlog = new PlayLog();

        $form = $this->createForm('AppBundle\Form\PlayLogType', $playlog);
        $form->handleRequest($request);

        $playlog->setGameId($gameId);
        echo $playlog->getGameId()."!";
        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($playlog);
            $em->flush();
//            return $this->redirectToRoute('game_show', array('id' => $gameId));
        }

        return $this->render('playlog/new.html.twig', array(
            'playLog' => $playlog,
            'form' => $form->createView(),
        ));
    }
        return $this->render('playlog/new.html.twig', array(
            'playLog' => $playLog,
            'form' => $form->createView(),
        ));
    }

    /**
     * Finds and displays a playLog entity.
     *
     * @Route("/{id}", name="playlog_show")
     * @Method("GET")
     */
    public function showAction(PlayLog $playLog)
    {
        $deleteForm = $this->createDeleteForm($playLog);

        return $this->render('playlog/show.html.twig', array(
            'playLog' => $playLog,
            'delete_form' => $deleteForm->createView(),
        ));
    }

    /**
     * Displays a form to edit an existing playLog entity.
     *
     * @Route("/{id}/edit", name="playlog_edit")
     * @Method({"GET", "POST"})
     */
    public function editAction(Request $request, PlayLog $playLog)
    {
        $deleteForm = $this->createDeleteForm($playLog);
        $editForm = $this->createForm('AppBundle\Form\PlayLogType', $playLog);
        $editForm->handleRequest($request);

        if ($editForm->isSubmitted() && $editForm->isValid()) {
            $this->getDoctrine()->getManager()->flush();

            return $this->redirectToRoute('playlog_edit', array('id' => $playLog->getId()));
        }

        return $this->render('playlog/edit.html.twig', array(
            'playLog' => $playLog,
            'edit_form' => $editForm->createView(),
            'delete_form' => $deleteForm->createView(),
        ));
    }

    /**
     * Deletes a playLog entity.
     *
     * @Route("/{id}", name="playlog_delete")
     * @Method("DELETE")
     */
    public function deleteAction(Request $request, PlayLog $playLog)
    {
        $form = $this->createDeleteForm($playLog);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->remove($playLog);
            $em->flush();
        }

        return $this->redirectToRoute('playlog_index');
    }

    /**
     * Creates a form to delete a playLog entity.
     *
     * @param PlayLog $playLog The playLog entity
     *
     * @return \Symfony\Component\Form\Form The form
     */
    private function createDeleteForm(PlayLog $playLog)
    {
        return $this->createFormBuilder()
            ->setAction($this->generateUrl('playlog_delete', array('id' => $playLog->getId())))
            ->setMethod('DELETE')
            ->getForm()
        ;
    }
}

--- game / log.html.twig

{% extends 'base.html.twig' %}
{% block content %}
    Adding log for {{ game.name }}
    {{ form_widget(form.playlogs) }}

    <input type="submit" value="Create" class="btn btn-default pull-left" />
{% endblock content %}

--- PlayLogType.php

<?php

namespace AppBundle\Form;

use AppBundle\Entity\PlayLog;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PlayLogType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('date');
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => PlayLog::class
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_playlog';
    }


}

--- GameType.php

   <?php

    namespace AppBundle\Form;

    use AppBundle\Entity\PlayLog;
    use Symfony\Component\Form\Extension\Core\Type\CollectionType;
    use Symfony\Component\Form\Extension\Core\Type\SubmitType;
    use Symfony\Component\Form\Extension\Core\Type\TextType;
    use Symfony\Bridge\Doctrine\Form\Type\EntityType;
    use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;

    class GameType extends AbstractType
    {
        /**
         * {@inheritdoc}
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('name', TextType::class, [
                    'attr' => [
                        'class' => 'form-control',
                    ],
                ]);
            $builder
                ->add('type', EntityType::class, [
                    'class' => 'AppBundle:Type',
                    'choice_label' => function ($type) {
                        return $type->getName();
                    },
                    'multiple' => false,
                    'expanded' => false,
                    'attr' => [
                        'class' => 'form-control',
                    ],

                ]);

            $builder->add('playlogs', CollectionType::class, array(
                'entry_type' => PlayLogType::class,
                'label' => false
            ));


        }

        /**
         * {@inheritdoc}
         */
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'AppBundle\Entity\Game'
            ));
        }

        /**
         * {@inheritdoc}
         */
        public function getBlockPrefix()
        {
            return 'appbundle_game';
        }


    }

2 个答案:

答案 0 :(得分:0)

不确定这是否是您要找的答案..

您可以在Playlog控制器中稍微调整newAction和他的Route注释,以便在路径中添加gameId

/**
 * Creates a new playLog entity.
 *
 * @Route("/{gameId}/new", name="playlog_new")
 * @Method({"GET", "POST"})
 */
public function newAction(Request $request, $gameId)
{
    $em = $this->getDoctrine()->getManager();

    $game = $em->getRepository('AppBundle:Game')->find($gameId);

    if(null === $game) {
        throw $this->createNotFoundException('The game with id ' . $gameId . ' does not exist.');
    }

    $playLog = new Playlog();
    $playLog->SetGame($game);
    $form = $this->createForm('AppBundle\Form\PlayLogType', $playLog);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em->persist($playLog);
        $em->flush($playLog);

        return $this->redirectToRoute('playlog_show', array('id' => $playLog->getId()));
    }

    return $this->render('playlog/new.html.twig', array(
        'playLog' => $playLog,
        'form' => $form->createView(),
    ));
}

答案 1 :(得分:0)

我已经弄清楚了,我试图坚持只有一个ID($ gameId),但它期待整个Game对象。 (1)所以我首先必须使用ID获取实际的存储库对象,之后我可以保留此对象:

   public function newAction(Request $request, $gameId)
    {
        $playlog = new PlayLog();
        $em = $this->getDoctrine()->getManager();
        // (1) Get Game object with given gameId:
        $game = $em ->getRepository(Game::class)->find($gameId);

        //Set the Game object
        $playlog->setGame($game);
        $form = $this->createForm('AppBundle\Form\PlayLogType', $playlog);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            /* @var $playLog PlayLog */
            $playlog = $form->getData();

            $em->persist($playlog);
            $em->flush();
        }

        return $this->render('playlog/new.html.twig', array(
            'playLog' => $playlog,
            'form' => $form->createView(),
        ));
    }