所以,1:M / M:1关系不像M:M关系那样工作(显然),但我认为通过适当的配置,你可以获得与M:M关系相同的输出.
基本上,我需要向path_offer添加另一个字段(位置).
我以为我开始工作,直到我尝试使用$path-> getOffers()返回一个PersistentCollection而不是我认为强制的(一个提供的ArrayCollection).无论如何,在当前表中,我有两个条目:两个提供到一个路径. $path-> getOffers()返回一个PathOffer的PersistantCollection,它只有一个Offer被附加,而不是两个.
我的问题是如何真正使用这些类型的关系?因为我需要这个项目的许多其他方面,我正在努力(许多M:M集合也需要定位)
我的代码如下!
Path.PHP
[..] /** * @ORM\Entity * @ORM\Table(name="path") */ class Path { /** * @var integer * * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ protected $id; /** * @ORM\OneToMany(targetEntity="PathOffer",mappedBy="offer",cascade={"all"}) */ protected $offers; [..]
PathOffer.PHP
[..] /** * @ORM\Entity * @ORM\Table(name="path_offer") */ class PathOffer { /** * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ protected $id; /** * @ORM\ManyToOne(targetEntity="Path",inversedBy="offers",cascade={"all"}) */ protected $path; /** * @ORM\ManyToOne(targetEntity="Offer",cascade={"all"}) */ protected $offer; /** * @ORM\Column(type="integer") */ protected $pos; [..]
Offer.PHP
[..] /** * @ORM\Entity * @ORM\Table(name="offer") */ class Offer { /** * @var integer * * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ protected $id; /** * @var \ZGoffers\MainBundle\Entity\PathOffer * * @ORM\OneToMany(targetEntity="PathOffer",mappedBy="path",cascade={"all"}) */ protected $paths; [..]
我想到了.希望这篇文章可以帮助那些像我一样沮丧的人!
Path.PHP
<?PHP namespace JStout\MainBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="path") */ class Path { /** * @var integer * * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var \JStout\MainBundle\Entity\PathOffer * * @ORM\OneToMany(targetEntity="PathOffer",cascade={"all"}) * @ORM\OrderBy({"pos" = "ASC"}) */ private $offers; [...]
PathOffer.PHP
<?PHP namespace JStout\MainBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="path_offer") */ class PathOffer { /** * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @ORM\ManyToOne(targetEntity="Path",cascade={"all"}) */ private $path; /** * @ORM\ManyToOne(targetEntity="Offer",inversedBy="paths",cascade={"all"}) */ private $offer; /** * @ORM\Column(type="integer") */ private $pos; [...]
Offer.PHP
<?PHP namespace JStout\MainBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="offer") */ class Offer { /** * @var integer * * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var \JStout\MainBundle\Entity\PathOffer * * @ORM\OneToMany(targetEntity="PathOffer",cascade={"all"}) */ private $paths; [...]
而对于我的前端逻辑:
PathController.PHP
<?PHP [...] /** * @Extra\Route("/path",name="admin_path") * @Extra\Route("/path/{id}/edit",name="admin_path_edit",requirements={"id" = "\d+"}) * @Extra\Template() */ public function pathAction($id = null) { $path = $this->_getObject('Path',$id); // this function either generates a new entity or grabs one from database depending on $id $form = $this->get('form.factory')->create(new Form\PathType(),$path); $formHandler = $this->get('form.handler')->create(new Form\PathHandler(),$form); // process form if ($formHandler->process()) { $this->get('session')->setFlash('notice','Successfully ' . ($this->_isEdit($path) ? 'edited' : 'added') . ' path!'); return $this->redirect($this->generateUrl('admin_path')); } return array( 'path' => $path,'form' => $form->createView(),'postUrl' => !$this->_isEdit($path) ? $this->generateUrl('admin_path') : $this->generateUrl('admin_path_edit',array('id' => $path->getId())),'paths' => $this->_paginate('Path'),'edit' => $this->_isEdit($path) ? true : false ); } [...]
PathType.PHP(路径形式)
<?PHP namespace JStout\MainBundle\Form; use Symfony\Component\Form\AbstractType,Symfony\Component\Form\FormBuilder; class PathType extends AbstractType { public function buildForm(FormBuilder $builder,array $options) { $builder ->add('name') ->add('title') ->add('offers','collection',array( 'type' => new PathOfferType(),'allow_add' => true,'allow_delete' => true )) ->add('active'); } public function getDefaultOptions(array $options) { return array( 'data_class' => 'JStout\MainBundle\Entity\Path' ); } }
PathOfferType.PHP(PathType的提供集合类型)
<?PHP namespace JStout\MainBundle\Form; use Symfony\Component\Form\AbstractType,Symfony\Component\Form\FormBuilder; class PathOfferType extends AbstractType { public function buildForm(FormBuilder $builder,array $options) { $builder ->add('offer','entity',array( 'class' => 'JStout\MainBundle\Entity\Offer','query_builder' => function($repository) { return $repository->createQueryBuilder('o')->orderBy('o.name','ASC'); },'property' => 'name' )) ->add('pos','integer'); } public function getDefaultOptions(array $options) { return array( 'data_class' => 'JStout\MainBundle\Entity\PathOffer' ); } }
PathHandler.PHP(我如何处理表单)
<?PHP namespace JStout\MainBundle\Form; use JStout\MainBundle\Component\Form\FormHandlerInterface,Symfony\Component\Form\Form,Symfony\Component\HttpFoundation\Request,Doctrine\ORM\EntityManager,JStout\MainBundle\Entity\Path; class PathHandler implements FormHandlerInterface { protected $form; protected $request; protected $entityManager; public function buildFormHandler(Form $form,Request $request,EntityManager $entityManager) { $this->form = $form; $this->request = $request; $this->entityManager = $entityManager; } public function process() { if ('POST' == $this->request->getMethod()) { // bind form data $this->form->bindRequest($this->request); // If form is valid if ($this->form->isValid() && ($path = $this->form->getData()) instanceOf Path) { // save offer to the database $this->entityManager->persist($path); foreach ($path->getOffers() as $offer) { $offer->setPath($path); $this->entityManager->persist($offer); } $this->entityManager->flush(); return true; } } return false; } }