doctrine2 один ко многим не работает
Это простая проблема, но после прохождения всех подобных потоков в Stackru и в других местах без успеха проблема остается.
Я не могу заставить работать двунаправленные отношения "один ко многим". Поле Biomass.field доступно (владеющая сторона), а Field.biomasses (обратная сторона) - нет.
Таблицы (удалены поля расходных материалов)
CREATE TABLE `field` (
`field_id` varchar(255) NOT NULL,
PRIMARY KEY (`field_id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `biomass` (
`biomass_id` int(11) NOT NULL AUTO_INCREMENT,
`field_id` varchar(255) NOT NULL,
PRIMARY KEY (`biomass_id`),
KEY `FK_field_has_0m_biomasses_idx` (`field_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `biomass`
ADD CONSTRAINT `FK_field_has_0m_biomasses` FOREIGN KEY (`field_id`) REFERENCES
`field` (`field_id`) ON DELETE CASCADE ON UPDATE CASCADE;
Field.php
<?php
namespace Acme\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Acme\MainBundle\Entity\Field
*
* @ORM\Table(name="field")
* @ORM\Entity
*/
class Field {
public function __construct() {
$this->biomasses = new ArrayCollection();
}
/**
* @var string $id
*
* @ORM\Column(name="field_id", type="string", length=255, nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/*
* var ArrayCollection $biomasses
*
* @ORM\OneToMany(targetEntity="Biomass", mappedBy="field", cascade={"all"})
*/
private $biomasses;
/**
* Get id
*
* @return integer
*/
public function getId() {
return $this->id;
}
/**
* Get biomasses
*
* @return ArrayCollection
*/
public function getBiomasses() {
return $this->biomasses;
}
/**
* Set biomasses
*
* @param ArrayCollection $biomasses
* @return ArrayCollection
*/
public function setBiomasses(ArrayCollection $biomasses) {
$this->biomasses = $biomasses;
return $this->biomasses;
}
/**
* Add Biomass
*
* @param Biomass $biomass
* @return ArrayCollection
*/
public function addBiomass(Biomass $biomass) {
$biomass->setField($this);
return $this->biomasses[] = $biomass;
}
/**
* Set biomass
*
* @param Biomass $biomass
* @return ArrayCollection
*/
public function removeBiomass(Biomass $biomass) {
return $this->biomasses->removeElement($biomass);
}
function __toString() {
return $this->getId();
}
}
Biomass.php
<?php
namespace Acme\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Acme\MainBundle\Entity\Biomass
*
* @ORM\Table(name="biomass")
* @ORM\Entity
*/
class Biomass {
/**
* @var integer $id
*
* @ORM\Column(name="biomass_id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var Field
*
* @ManyToOne(targetEntity="Field", inversedBy="biomasses")
* @JoinColumn(name="field_id", referencedColumnName="field_id")
*/
private $field;
/**
* Get id
*
* @return string
*/
public function getId() {
return $this->id;
}
/**
* Set field
*
* @param Field $field
* @return Biomass
*/
public function setField(Field $field = null) {
//$field->addBiomass($this);
$this->field = $field;
return $this;
}
/**
* Get field
*
* @return Field
*/
public function getField() {
return $this->field;
}
function __toString() {
return $this->id;
}
}
FieldController.php
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository("AcmeMainBundle:Field")->findAll();
foreach($entities as $field) {
foreach($field->getBiomasses() as $biomass) {
print_r($biomass->getId());
}
}
Это приводит к следующему: Предупреждение: неверный аргумент передан foreach() в строке C:[...]\MainBundle\Controller\FieldController.php 39
ArrayCollecion не создается, поскольку Doctrine не вызывает конструкторы, а использует трюк сериализации / десериализации для создания экземпляров классов.
У меня есть фиктивные данные в этих таблицах, и эти данные доступны, поэтому кажется, что доктрина вообще не создает объект биомассы.
Среда Symfony-2.1.2, Apache/2.4.3 (Win64), PHP/5.4.6-Win64, MySQL Community Server 5.5.28
РЕДАКТИРОВАТЬ: исправлено опечатка имени столбца Biomass.field.
1 ответ
В BioMass.php @JoinColumn должен указывать на field_id, а не id в таблице BioMass.
/**
* @var Field
*
* @ManyToOne(targetEntity="Field", inversedBy="biomasses")
* @JoinColumn(name="field_id", referencedColumnName="field_id")
*/