php Doctrine2 一对多/多对一关系
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6514365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Doctrine2 One-To-Many / Many-To-One relations
提问by Jordan
So, 1:M / M:1 relations don't work the way M:M relations work (obviously), but I thought that with proper configuration, you can get the same output as a M:M relation.
因此,1:M / M:1 关系不像 M:M 关系那样工作(显然),但我认为通过适当的配置,您可以获得与 M:M 关系相同的输出。
Basically, I needed to add another field (position), to path_offer
.
基本上,我需要将另一个字段(位置)添加到path_offer
.
I thought I got it to work until I tried to use $path->getOffers()
which returned a PersistentCollection
instead of what I thought is forced (an ArrayCollection
of Offers). Anyway, inside the current table, I have two entries: two offers to one path. $path->getOffers()
is returning a PersistantCollection
of a PathOffer
which only has one Offer
attatched and not both.
我以为我可以正常工作,直到我尝试使用$path->getOffers()
which 返回了一个PersistentCollection
而不是我认为是被迫的(一个ArrayCollection
优惠)。无论如何,在当前表中,我有两个条目:一条路径的两个报价。 $path->getOffers()
正在返回 aPersistantCollection
的 a PathOffer
,其中只Offer
附加了一个,而不是两者都附加。
My question is how to really use these types of relations? Because I need it with many other aspects of this project I'm working on (many M:M collections also need to be positioned)
我的问题是如何真正使用这些类型的关系?因为我正在处理的这个项目的许多其他方面都需要它(许多 M:M 集合也需要定位)
My code is below!
我的代码在下面!
Path.php
路径.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
路径报价.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", inversedBy="offers", cascade={"all"})
*/
protected $offer;
/**
* @ORM\Column(type="integer")
*/
protected $pos;
[..]
Offer.php
报价.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;
[..]
采纳答案by Jordan
I figured it out. Hopefully this post can help others who got as frustrated as I did!
我想到了。希望这篇文章可以帮助其他和我一样沮丧的人!
Path.php
路径.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", mappedBy="path", cascade={"all"})
* @ORM\OrderBy({"pos" = "ASC"})
*/
private $offers;
[...]
PathOffer.php
路径报价.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", inversedBy="offers", cascade={"all"})
*/
private $path;
/**
* @ORM\ManyToOne(targetEntity="Offer", inversedBy="paths", cascade={"all"})
*/
private $offer;
/**
* @ORM\Column(type="integer")
*/
private $pos;
[...]
Offer.php
报价.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", mappedBy="offer", cascade={"all"})
*/
private $paths;
[...]
And for my frontend logic:
对于我的前端逻辑:
PathController.php
路径控制器.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 (the path form)
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's offers collection type)
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 (how I process the form)
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;
}
}
回答by timdev
Looks like you're doing it right. Don't worry about the PersistentCollection
/ArrayCollection
stuff -- all that matters is that they're collections.
看起来你做得对。不要担心PersistentCollection
/ArrayCollection
东西——重要的是它们是集合。
$Path->getOffers()
should indeed return a collection of PathOffers
, and each PathOffer
should have an offer.
$Path->getOffers()
确实应该返回 的集合PathOffers
,并且每个都PathOffer
应该有一个报价。
So it ought to work like this:
所以它应该像这样工作:
//Output a all offers associated with a path, along with the position.
$pathOffers = $path->getOffers();
foreach($pathOffers as $po){
echo $po->getOffer()->id . ' [' . $po->getPosition() . "]\n";
}
Am I missing something?
我错过了什么吗?