【问题标题】:Doctrine Entity extending another Entity教义实体扩展另一个实体
【发布时间】:2013-10-13 11:09:13
【问题描述】:

您好,我阅读了这篇文章 http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html,但我不确定如何完成以下操作:

我有一个“用户”表、一个“男人”表和一个“女人”表。 我希望我的 php 类 ManWoman 扩展 User 对象。

注解映射:

    namespace Core\Entity;

    use Doctrine\ORM\Mapping as ORM;

    /**
     * User
     *
     * @ORM\Table(name="user", uniqueConstraints={@ORM\UniqueConstraint(name="email_UNIQUE", columns={"email"}), @ORM\UniqueConstraint(name="username_UNIQUE", columns={"username"})})
     * @ORM\Entity
     */
    class User
    {
        /**
         * @var integer
         *
         * @ORM\Column(name="id", type="integer", nullable=false)
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="IDENTITY")
         */
        private $id;

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

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

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

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

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

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

        /**
         * @var \DateTime
         *
         * @ORM\Column(name="created_at", type="datetime", nullable=true)
         */
        private $createdAt;

        /**
         * @var \DateTime
         *
         * @ORM\Column(name="updated_at", type="datetime", nullable=false)
         */
        private $updatedAt;

        /**
         * @var \DateTime
         *
         * @ORM\Column(name="last_login", type="datetime", nullable=false)
         */
        private $lastLogin;

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

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

        /**
         * @var \Doctrine\Common\Collections\Collection
         *
         * @ORM\ManyToMany(targetEntity="Core\Entity\Bill", inversedBy="user")
         * @ORM\JoinTable(name="user_has_bill",
         *   joinColumns={
         *     @ORM\JoinColumn(name="user_id", referencedColumnName="id")
         *   },
         *   inverseJoinColumns={
         *     @ORM\JoinColumn(name="bill_id", referencedColumnName="id")
         *   }
         * )
         */
        private $bill;

        /**
         * @var \Doctrine\Common\Collections\Collection
         *
         * @ORM\ManyToMany(targetEntity="Core\Entity\Picture", inversedBy="user")
         * @ORM\JoinTable(name="user_has_picture",
         *   joinColumns={
         *     @ORM\JoinColumn(name="user_id", referencedColumnName="id")
         *   },
         *   inverseJoinColumns={
         *     @ORM\JoinColumn(name="picture_id", referencedColumnName="id")
         *   }
         * )
         */
        private $picture;

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

    }

女人:

namespace Core\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Woman
 *
 * @ORM\Table(name="woman", indexes={@ORM\Index(name="fk_woman_user1_idx", columns={"user_id"})})
 * @ORM\Entity
 */
class Woman
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $id;

    /**
     * @var \Core\Entity\User
     *
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     * @ORM\OneToOne(targetEntity="Core\Entity\User")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     * })
     */
    private $user;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="Core\Entity\Cart", inversedBy="woman")
     * @ORM\JoinTable(name="woman_has_cart",
     *   joinColumns={
     *     @ORM\JoinColumn(name="woman_id", referencedColumnName="id")
     *   },
     *   inverseJoinColumns={
     *     @ORM\JoinColumn(name="cart_id", referencedColumnName="id")
     *   }
     * )
     */
    private $cart;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="Core\Entity\Interest", inversedBy="woman")
     * @ORM\JoinTable(name="woman_has_interest",
     *   joinColumns={
     *     @ORM\JoinColumn(name="woman_id", referencedColumnName="id")
     *   },
     *   inverseJoinColumns={
     *     @ORM\JoinColumn(name="interest_id", referencedColumnName="id")
     *   }
     * )
     */
    private $interest;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="Core\Entity\Man", inversedBy="woman")
     * @ORM\JoinTable(name="woman_has_man",
     *   joinColumns={
     *     @ORM\JoinColumn(name="woman_id", referencedColumnName="id")
     *   },
     *   inverseJoinColumns={
     *     @ORM\JoinColumn(name="man_id", referencedColumnName="id")
     *   }
     * )
     */
    private $man;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->cart = new \Doctrine\Common\Collections\ArrayCollection();
        $this->interest = new \Doctrine\Common\Collections\ArrayCollection();
        $this->man = new \Doctrine\Common\Collections\ArrayCollection();
    }

}

男人映射看起来(现在)和女人一样。

这里有一个来自 MysqlWorkbench http://s14.directupload.net/images/131013/fbg7okyn.png 的小片段

基本思路是这样的:

男人和女人有一些共同的逻辑和个人的逻辑。例如登录。男性和女性需要电子邮件和密码才能登录。由于两次实现相同的登录逻辑是多余的,我想创建一个更抽象的类,User,我想在其中放置适用于男性和女性,例如姓名、电子邮件、密码、登录逻辑等...

这就是教义变得棘手的地方。男性和女性将有单独的字段存储在数据库中,但他们仍然需要他们的“公共数据”(姓名、密码等......),所以一个简单的class Man extends User 可能无法正常工作。我将User 的相应id 存储在男性和女性身上。所以有一个标识。

我的想法是,如果我做$men->getPassword(),它应该使用相应User对象的getPassword()函数。

我希望我清除了我的意图。

诚挚的问候,感谢您的深入研究。

【问题讨论】:

    标签: php doctrine-orm zend-framework2


    【解决方案1】:

    我曾经在我的一个项目中完成了您正在寻找的事情,它在代码方面做得不太好,但映射很好;)请检查this link

    • Item.php.dist 将是您的用户实体
    • (Property|Vehicle).php.dist 将是您的男人/女人实体
    • 请注意,代码示例中缺少属性鉴别器映射。我在应用程序中的做法有所不同;)

    最终,您不希望在 SQL Server 上拥有单独的“表”。它都属于超类“用户”,因此属于用户表。您将扩展 UserTable 并使用 DiscriminatorMapping 映射特定实体。

    注意:不能将男人编辑为女人!你必须杀死那个男人并生下一个女人:P

    想象一下这个模型:

    User
      *id
      -name
      -surname
    
    Man extends User
      -pc_power
    
    Woman extends User
      -nail_color
    

    您的 DB-Schema 如下所示:

    Table User:
      *id (pk)
      -discriminator (not nullable) (value: man or woman)
      -name (not nullable)
      -surname (not nullable)
      -pc_power (nullable as far as DB is concerned)
      -nail_color (nullable as far as DB is concerned)
    

    您不需要 3 个表格来像这样修改您的模型。这样做实际上没有任何意义。它只会让您的查询速度减慢很多。

    现在数据集可能如下所示:

    A Man: (1, man, john, doe, 4ghz, null)
    A Woman: (2, woman, john, doe, null, pink)
    

    现在在 Doctrine 方面,您对 USER-Entity 进行查询

    $entity = $userRepository->find(1);
    echo get_class($entity); // returns "Man"
    
    $entity = $userRepository->find(2);
    echo get_class($entity); // returns "Woman"
    

    这会让事情更清楚吗,否则我根本无法帮助你:P

    【讨论】:

    • 嗨,山姆,我从你的页面学到了很多 zf2。但回到主题。由于男性和女性需要登录,我认为具有所有基本字段(如电子邮件、密码等)的“用户”会很好,而且由于男性和女性是分开对待的,所以我想制定这种逻辑,而不是把所有东西都放在用户身上。在您的 github 上,我认为我不需要接口,但似乎因为我在 womanmen 上放置了单独的 id,映射将中断。 MySqlWorkbench 模型会有帮助吗?
    • 您可能需要进一步解释您的实际问题。最终,我的实体“项目”等于您的“用户”,“财产”和“车辆”都等于您的“男人”和“女人”。两者的逻辑/数据进入用户,男性/女性的逻辑/数据进入各自的实体
    • @Soundz Workbench 的图片有点“没用”——你只需要一个字段“is_man”或“is_woman”,它是真/假。如果您需要共享逻辑,我只能敦促您尝试理解我提供给您的代码。它完全符合您的要求。但它使用不同的 DB-Schema。不要先使用 DB-Schema。学说遵循模型优先原则。在我看来,您似乎不了解学说的继承映射:S
    • 那是真的,它不是很清楚。但只是为了说清楚:你理解我的方法是共享的和个人的逻辑吗? - 好的。但是,如果我让您正确,我就无法按照我的意图将这种方法转换为教义。我知道学说遵循模型优先,但对我来说更容易规划我的初始数据库布局更加直观。
    • @Soundz 请看我的编辑,如果这没有帮助,我无能为力:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-04
    • 2019-04-21
    相关资源
    最近更新 更多