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")
 */
Другие вопросы по тегам