dqj29136 2015-08-03 00:12
浏览 108

在Zend框架2中使用MappedSuperclass进行多对多的Doctrine 2

I am new to Doctrine2 and trying to create entities for the following DB structure: enter image description here

I want to have all machine parts as an array in one attribute of the machine class. I tried this:

class Machine {
    ....
    /**
     * @var array
     * @ORM\OneToMany(targetEntity="MachineHasPart", mappedBy="machine", cascade={"persist", "remove"}, orphanRemoval=TRUE)
     */
    private $parts;
    ....

    public function getParts () {
        return array_map(
            function ($machineHasPart) {
                return $machineHasPart->getPart();
            },
            $this->parts->toArray()
        );
    }
}

Where MachineHasPart is a @MappedSuperclass for the intermediate entities/tables (like machineHasCylinder etc), but it failed with:

An exception occurred while executing 'SELECT FROM machineHasPart t0'.

Should I restructure my database to use ORM here? Or there is a solution for my case?

  • 写回答

2条回答 默认 最新

  • dsgd5756 2015-08-03 08:12
    关注

    You cannot query a @MappedSuperClass. This is also mentioned in the Doctrine2 documentation in chapter 6.1. Mapped Superclasses:

    A mapped superclass cannot be an entity, it is not query-able and persistent

    This means you have to either change the target entity to something queryable or you have to make MachineHasPart to a entity and change to single table inheritance.

    When I look at your database structure I would suggest changing your Machine entity to have three independent relationships for the parts. One for Belt, one for Cylinder and one for Gear.

    Then instead of a generic getParts you will have three methods getBelts, getCylinders and getGears.

    If that is really not what you want then you can leave a comment.

    UPDATE

    You can solve it also with class inheritance. First make a base class Part that is also an entity and use it in the other classes Belt, Cylinder and Gear:

    Part:

    <?php
    
    namespace Machine\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * Part
     *
     * @ORM\Entity
     * @ORM\Table("part")
     * @ORM\InheritanceType("SINGLE_TABLE")
     * @ORM\DiscriminatorColumn(name="discriminator", type="string")
     * @ORM\DiscriminatorMap({
     *     "part" = "Part",
     *     "gear" = "Gear",
     *     "cylinder" = "Cylinder",
     *     "belt" = "Belt",
     * })
     * @property int $id
     */
    class Part
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;
    
        /**
         * @var Machine
         * @ORM\ManyToOne(targetEntity="Machine\Entity\Machine", inversedBy="parts")
         * @ORM\JoinColumn(name="machine_id", referencedColumnName="id", nullable=true)
         */
        protected $machine;
    
        /**
         * Get id.
         *
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }
    
        /**
         * Set id.
         *
         * @param int $id
         * @return self
         */
        public function setId($id)
        {
            $this->id = $id;
    
            return  $this;
        }
    
        //... add setters and getters for machine as normal ...
    }
    

    Extend this class in your other parts:

    Belt:

    <?php
    
    namespace Machine\Entity;
    
    /**
     * Belt
     *
     * @ORM\Entity
     */
    class Belt extends Part
    {
    }
    

    Cylinder:

    <?php
    
    namespace Machine\Entity;
    
    /**
     * Cylinder
     *
     * @ORM\Entity
     */
    class Cylinder extends Part
    {
    
    }
    

    Gear:

    <?php
    
    namespace Machine\Entity;
    
    /**
     * Gear
     *
     * @ORM\Entity
     */
    class Gear extends Part
    {
    
    }
    

    Now in your machine relate to the parts like as follows.

    Machine:

    <?php
    
    namespace Machine\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    use Doctrine\Common\Collections\Collection;
    use Doctrine\Common\Collections\ArrayCollection;
    
    /**
     * Machine
     *
     * @ORM\Entity
     * @ORM\Table("machine")
     * @property int $id
     */
    class Machine
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;
    
        /**
         * Get id.
         *
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }
    
        /**
         * Set id.
         *
         * @param int $id
         * @return self
         */
        public function setId($id)
        {
            $this->id = $id;
    
            return  $this;
        }
    
        /**
         * @var Collection
         * @ORM\OneToMany(targetEntity="Machine\Entity\Part", mappedBy="machine")
         */
        protected $parts;
    
        public function __constuct()
        {
            $parts = new ArrayCollection();
        }
    
        /**
         *
         * @return Collection
         */
        public function getParts()
        {
            return $this->parts;
        }
    
        //... add setters and getters for parts as normal ...
    }
    

    Extend this class in your other parts:

    评论

报告相同问题?

悬赏问题

  • ¥30 酬劳2w元求合作写文章
  • ¥15 在现有系统基础上增加功能
  • ¥15 远程桌面文档内容复制粘贴,格式会变化
  • ¥15 关于#java#的问题:找一份能快速看完mooc视频的代码
  • ¥15 这种微信登录授权 谁可以做啊
  • ¥15 请问我该如何添加自己的数据去运行蚁群算法代码
  • ¥20 用HslCommunication 连接欧姆龙 plc有时会连接失败。报异常为“未知错误”
  • ¥15 网络设备配置与管理这个该怎么弄
  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图