Reputation: 1300
Hi I read this article http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html yet I'm not quiet sure how to accomplish the following:
I have a "user"-Table, a "man"-Table and a "woman"-table.
I want my php classes Man
and Woman
extend the User
Object.
Annotationmapping:
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();
}
}
Woman:
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();
}
}
The man mapping looks (for now) the same as the woman.
Here a little Snippet from MysqlWorkbench http://s14.directupload.net/images/131013/fbg7okyn.png
The basic idea is this:
Men and Women share some common logic and individual logic. For example take a login. Men and Women need an email and a password to log in. Since it's redundant to implement the same login logic twice I thought of creating a more abstract class, the User
, which is where I want to put everything which applies to men and women, like name, email, password, login logic etc...
This is where it gets tricky with doctrine. Men and women will have individual fields to store in the database, yet they still need their "common data"(name, password etc...), so a simple class Man extends User
might not work out correctly. I store the corresponding id of the User
on men and women. So there is an identification.
What I had in mind is, if I do $men->getPassword()
it should use the getPassword()
function of the corresponding User
object.
I hope I cleared up my intend.
Kind Regards and thank you for digging through.
Upvotes: 0
Views: 385
Reputation: 16455
i have done this what you're looking for in one of my projects once, It's done not too good code wise, but the mapping is fine ;) Please check this link
Ultimately you wouldn't want to have separate "Tables" on your SQL Server. It all belongs to the Superclass "User" and therefore belongs to the User-Table. You will extends the UserTable and use DiscriminatorMapping to map specific entities.
Note: A Man can not be editted to become a Woman! You'd have to kill the man and give birth to a woman :P
Imagina this Model:
User
*id
-name
-surname
Man extends User
-pc_power
Woman extends User
-nail_color
Your DB-Schema would look like this:
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)
You do not need 3 tables to mod your models like this. It makes literally no sense to do this. It just slows your Queries down by quite a bit.
Now a Dataset could look like this:
A Man: (1, man, john, doe, 4ghz, null)
A Woman: (2, woman, john, doe, null, pink)
Now on Doctrines side of things you do Queries against the USER-Entity
$entity = $userRepository->find(1);
echo get_class($entity); // returns "Man"
$entity = $userRepository->find(2);
echo get_class($entity); // returns "Woman"
Does that make things more clear, because otherwise i'm simply unable to help you :P
Upvotes: 2