Doctrine2让我对OneToMany和ManyToOne的关系感到疯狂

时间:2014-03-08 10:48:51

标签: postgresql zend-framework orm doctrine-orm zend-framework2

我尝试使用Doctrine2 Mapping,但是经过8小时的问题后,我真的需要你的帮助。

我有3个PostgreSQL表,第一个是房子

 Column  |      Type      |                     Modifiers                      
---------+----------------+----------------------------------------------------
 id      | integer        | not null default nextval('house_id_seq'::regclass)
 name    | character(255) | not null
 address | character(255) | 
 rooms   | integer        | not null
Indexes:
    "house_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "room" CONSTRAINT "room_house_id_fkey" FOREIGN KEY (house_id) REFERENCES house(id) ON UPDATE CASCADE ON DELETE CASCADE

,第二个是

Table "public.room"
  Column   |          Type          |                     Modifiers                     
-----------+------------------------+---------------------------------------------------
 id        | integer                | not null default nextval('room_id_seq'::regclass)
 name      | character varying(255) | 
 room_type | integer                | 
 vacant    | boolean                | 
 house_id  | integer                | 
Indexes:
    "room_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "room_house_id_fkey" FOREIGN KEY (house_id) REFERENCES house(id) ON UPDATE CASCADE ON DELETE CASCADE

,最后一个是

 Table "public.category"
   Column   |      Type      |                       Modifiers                       
------------+----------------+-------------------------------------------------------
 id         | integer        | not null default nextval('category_id_seq'::regclass)
 name       | character(255) | not null
 min_person | integer        | not null
 max_person | integer        | not null
Indexes:
    "category_pkey" PRIMARY KEY, btree (id)

我在room_house_id上​​插入了一个引用House表上的house.id的FK。

在我的Zend Framework2中,我的实体声明为

namespace Structures\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Structures\Entity\House
 *
 * @ORM\Table(name="house")
 * @ORM\Entity(repositoryClass="Structures\Entity\Repository\HouseRepository")
 */

class House
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName="house_id_seq", allocationSize=1, initialValue=1)
     */
    private $id;

    /**
     * @var string $name
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @var string $address
     *
     * @ORM\Column(name="address", type="string", length=255)
     */
    private $address;

    /**
     * @var string $rooms
     *
     * @ORM\Column(name="rooms", type="integer", nullable=false)
     */
    private $rooms;

    /**
     *
     * @ORM\OneToMany(targetEntity="Structures\Entity\Room", mappedBy="house", cascade={"remove", "persist"})
     */
    protected $house_room;
}


/**
 * Structures\Entity\Room
 *
 * @ORM\Table(name="room")
 * @ORM\Entity(repositoryClass="Structures\Entity\Repository\RoomRepository")
 */

class Room {

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

    /**
     * @var string $name
     *
     * @ORM\Column(name="name", type="string", length=255,nullable=false)
     */
    private $name;


    /**
     * @var boolean $vacant
     *
     * @ORM\Column(name="vacant", type="boolean", nullable=false)
     */
    private $vacant;


    /**
     * @var Structures\Entity\Category
     *
     * @ORM\ManyToOne(targetEntity="Structures\Entity\Category" , cascade={"persist", "remove"})
     * @ORM\JoinColumns({
     *  @ORM\JoinColumn(name="room_type", referencedColumnName="id")
     * })
     */
    private $category;


    /**
     * @ORM\ManyToOne(targetEntity="Structures\Entity\House", inversedBy="house_room", cascade={"remove", "persist"})
     *
     */
    private $house;
}

/**
 * Structures\Entity\Category
 *
 * @ORM\Table(name="category")
 * @ORM\Entity(repositoryClass="Structures\Entity\Repository\CategoryRepository")
 *
 */

class Category {

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

    /**
     * @var string $name
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     *
     */
    private $name;

    /**
     * @var integer $min_person
     * @ORM\Column(name="min_person", type="integer" , nullable=false)
     */
    private $min_person;

    /**
     * @var integer $max_person
     * @ORM\Column(name="max_person", type="integer", nullable=false)
     */
    private $max_person;
}

与房间和类别的关系也起作用。

一个关注的房间和房子表根本不起作用。我无法成功将FK house_id映射到House表上的id列。所有编辑/保存操作均失败,house_id始终设置为NULL

请让我明白我犯错的地方,我疯了

更新:

我试图改变House和Room之间的关系。 我删除了House的OneToMany并更改了

中的ManyToOne
/**
 * @var Structure\Entity\Structure
 *
 * @ORM\ManyToOne(targetEntity="Structures\Entity\House")
 * @ORM\JoinColumns({
 *  @ORM\JoinColumn(name="house_id", referencedColumnName="id", nullable=FALSE)
 * })
 */
private $house;

当我用

取回房间时
$room = $this->roomService->getRoom($id);
var_dump($room);

我有

object(Structures\Entity\Room)#383 (4) 
{ 
    ["id":"Structures\Entity\Room":private]=> int(77)             
    ["name":"Structures\Entity\Room":private]=> string(33) "my room" 
    ["structure":"Structures\Entity\Room":private]=> object(Structures\Entity\House)#339 (4) { 
    ["id":"Structures\Entity\House":private]=> int(3) 
    ["name":"Structures\Entity\House":private]=> string(255) "hotel2b " 
    ["address":"Structures\Entity\House":private]=> string(255) "hotel2b avenue" 
    ["number_of_rooms":"Structures\Entity\House":private]=> int(20) } 
    ["house_id":"Structures\Entity\Room":private]=> int(3) 
}

如果我使用OneToMany关系,var_dump($ room)会返回一整页,我不知道这意味着什么转储!

但是,编辑房间时,列house_is总是设置为NULL。 仍在努力

更新:3月9日

花了几个小时阅读教程后,我从头开始编写所有内容。 House Entity不再退出。结构实体是新的实体。 我的问题:使用Doctrine2添加和编辑OneToMany和ManyToOne关系的数据。

我的解决方案:

我的实体是 namespace Structures \ Entity;

将Doctrine \ ORM \ Mapping用作ORM;

/**
 * Structures\Entity\Structure
 *
 * @ORM\Table(name="room")
 * @ORM\Entity(repositoryClass="Structures\Entity\Repository\RoomRepository")
 */

class Room {

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

/**
 * @var string $name
 *
 * @ORM\Column(name="name", type="string", length=255,nullable=false)
 *
 */
private $name;

/**
 * @var integer structure_id
 * @ORM\Column(name="structure_id", type="integer", nullable=false)
 */
private $structure_id;

/**
 * @var Structure\Entity\Structure
 *
 * @ORM\ManyToOne(targetEntity="Structure", inversedBy="rooms")
 * @ORM\JoinColumns({
 *  @ORM\JoinColumn(name="structure_id", referencedColumnName="id")
 * })
 */
private $structure;




public function __construct()
{
  //  $this->structure = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * @param $data
 */
public function exchangeArray($data)

{
    $this->fillWith($data);
}


/**
 * @param $data
 * @return Room
 */
public static function createFromArray($data)
{
    $room = new Room();
    $room->fillWith($data);
    return $room;
}

public function updateFromArray($room)
{
    $structure_id = $room->getStructureId();
    $structure = $this->getStructure($structure_id);
    $room->setStructure($structure);
    return $room;


}




/**
 * Sets id
 * @param $i_id
 */
private function set_Id($i_id) {
    $this->id = $i_id;
}
/**
 * Gets id
 * @return integer
 *
 */
public function getId() {
    return $this->id;
}

/**
 * Set name
 * @param string name
 *
 */
public function setName($name) {
    $this->name = $name;
}
/**
 * Get name
 * @return string
 *
 */
public function getName() {
    return $this->name;
}
public function getStructureId()
{
    return $this->structure_id;
}

/**
 *
 * @return \Doctrine\Common\Collections\ArrayCollection|Structure\Entity\Structure
 */
public function getStructure() {
    return $this->structure;
}

public function setStructure($structure) {
    $this->structure = $structure;
}

和结构

namespace Structures\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Structures\Entity\Structure
 *
 * @ORM\Table(name="structure")
 * @ORM\Entity(repositoryClass="Structures\Entity\Repository\StructureRepository")
 */

class Structure {


/**
 * @var integer $id
 *
 * @ORM\Column(name="id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="SEQUENCE")
 * @ORM\SequenceGenerator(sequenceName="structure_id_seq", allocationSize=1, initialValue=1)

 *
 */
private $id;

/**
 *  @var string address
 *
 * @ORM\Column(name="name", type="string", length=255,nullable=false)
 */
private $name;

/**
 * @var string address
 *
 * @ORM\Column(name="address", type="string", length=255,nullable=false)
 *
 */
private $address;


/**
 * @var integer $rooms
 *
 * @ORM\Column(name="number_of_rooms", type="integer",  nullable=false)
 */
private $number_of_rooms;


/**
 * @ORM\OneToMany(targetEntity="Room", mappedBy="structure")
 */
private $rooms;


public function __construct() {
    $this->rooms = new \Doctrine\Common\Collections\ArrayCollection();
}






public function exchangeArray($data) {
    $this->fillWith($data);
}
public static function createFromArray($data)
{
    $structure = new Structure();
    $structure->fillWith($data);
    return $structure;
}
private function set_Id($i_id) {
    $this->id = $i_id;
}
/**
 * Get id
 * @return integer
 *
 */
public function getId() {
    return $this->id;
}

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

/**
 * Set address
 * @param string address
 *
 */
public function setAddress($address) {
    $this->address = $address;
}

/**
 * Get address
 * @return string
 *
 */
public function getAddress() {
    return $this->address;
}
/**
 * Set rooms
 * @params integer rooms
 *
 */
public function setRoom($room) {
    $this->rooms = $room;
}

/**
 * Get rooms
 * @return integer
 *
 */
public function getRoom() {
    return $this->rooms;
}

/**
 * @param $rooms
 */
public function setNumberOfRooms($number_of_rooms) {
    $this->number_of_rooms = $number_of_rooms;
}
/**
 * @return int
 */
public function getNumberOfRooms() {
    return $this->number_of_rooms;
}

当我创建一个新房间时,我调用一个函数来处理我的Zend \ Form \ Form数据

public function processForm() {
  if ($this->request->isPost()) {
        // get the post data
        $post = $this->request->getPost()->toArray();
        // fill form
        $this->form->setData($post);
        // check if form is valid
        if (!$this->form->isValid()) {
            //prepare view
            $view = new ViewModel(array('form' => $this->form,
                                        'title' => 'Process Form : 
              Some errors during rooms processing'));
            $view->setTemplate('structures/rooms/create');
                return $view;
        }
        /* here I set the structure's Id from $structure obj gets from 
          $this->params('id') 
        */
        $structure = $this->getStructureFromQuerystring();
        $post['structure_id'] = $structure->getId();

        /* here I call a service method to create a Room instance and fills it 
           with data from $this->form
        */
        $return = $this->roomService->insertRoomFromArray($post);

        if ($return ) {
            $this->flashMessenger()->setNamespace('rooms')->addMessage
            ('Operation executed correctly');
            return $this->redirect()->toRoute('rooms/index');

        } 
     }

服务方法

public function insertRoomFromArray(array $am_formData) {

    /* here I get the structure with the id stores in $am_formData*/
    $structure = $this->getStructure($am_formData['structure_id']);
    /* here I copy the $structure obj in $am_formData array */
    $am_formData['structure'] = $structure;
    /* here I call the Room Entity method createFromArray to create the Room */
    $I_event = Room::createFromArray($am_formData);
    /* here I call the mapper method to persist data */
    $this->I_mapper->saveRoom($I_event);

    return $I_event;

}

房间实体

public static function createFromArray($data)
{
    /* create new Room obj */
    $room = new Room();
    /* fill with data */
    $room->fillWith($data);
    return $room;
}
public function fillWith($data) {

    $this->id = (isset($data['id'])) ? $data['id'] : null;
    $this->name = (isset($data['name'])) ? $data['name'] : null;
    /* here I copy the structure obj for relationship */
    $this->structure = (isset($data['structure'])) ? $data['structure'] : null;
} 

Mapper实体     公共功能saveRoom(\ Structures \ Entity \ Room $ room)     {

    $this->entityManager->persist($room);
    $this->entityManager->flush();

}

它有效并且新房间具有正确结构的id集。

什么时候我需要编辑房间?我的解决方案

来自控制器

public function editAction() {

   /* Gets the room obj by $this->params('id') */

   $room = $this->getRoomFromQueryString();


    $this->form->bind($room);

    $view = $this->processEditForm($room);

    if (!$view instanceof ViewModel) {

        $view = new ViewModel(array('form' => $this->form,
            'title' => 'Edit Room: ' . $room->getName() , 
            'structure' => $room->getStructure()));
        $view->setTemplate('structures/rooms/create');

    }

    return $view;

}

private function processEditForm(Room $room)
{
    if ($this->request->isPost()) {
        $post = $this->request->getPost()->toArray();

       /* here I put structure_id in $post array. */

        $post['structure_id'] = $room->getStructure()->getId();

        /* After this , my previous room obj is update with the data come from the
           From, but the $structure entity is NULL. I don't know why. I will use the id
           stores in $post['structure_id'] to fetch the Structure obj*/ 
        $this->form->setData($post);


        if (!$this->form->isValid()) {
            $view = new ViewModel(array('form' => $this->form,
            'title' => 'Some erros during rooms processing'));
            $view->setTemplate('structures/rooms/create');
            return $view;
        }

         $return = $this->roomService->updateRoomFromArray($room);

        if ($return ) {
            $this->flashMessenger()->setNamespace('rooms')->addMessage('Operation executed correctly');
            return $this->redirect()->toRoute('rooms/index');
        }
        else {
            echo "Errore durante Editing della room";
        }

    }


}

更新数据的服务方法       public function updateRoomFromArray(Room $ room){          / *我调用Room Entity方法来更新我的房间 /          $ I_event = Room :: updateFromArray($ room);          / 持久数据* /          $这 - > I_mapper-> updateRoom($室);      }

public function updateFromArray($room)
{
    /* here I fetch the Structure's relationship my Room obj belongs to */
    $structure_id = $room->getStructureId();
    $structure = $this->getStructure($structure_id);
    /* here I set the link*/
    $room->setStructure($structure);
    return $room;


}
public function updateRoom(\Structures\Entity\Room $room)
{
    $this->entityManager->merge($room);
    $this->entityManager->flush();
}

我想知道您对我的代码的看法。使用Doctrine2是正确的方法吗?提前谢谢

1 个答案:

答案 0 :(得分:0)

注释的语法不正确。

您的ManyToOne关联必须具有以下简单格式:

@ManyToOne(targetEntity =“Structures \ Entity \ House”,inversedBy =“features”) @JoinColumn(name =“house_id”,referencedColumnName =“id”)

查看文档以获取更多信息: http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#one-to-many-bidirectional

希望这有帮助。

穆罕默德。