When I try to make a OneToMany unidirectional association between this two entities i get this error when i try to update the database schema:
$ app/console doctrine:schema:update --dump-sql
[Doctrine\ORM\Mapping\MappingException]
OneToMany mapping on field 'address' requires the 'mappedBy' attribute.
/**
* User
*
* @ORM\Table()
* @ORM\Entity
*/
class User
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\OneToMany(targetEntity="Address")
* @ORM\JoinTable(name="users_address",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="address_id", referencedColumnName="id", unique=true)}
* )
*/
private $address;
//...
}
/**
* Address
*
* @ORM\Table()
* @ORM\Entity
*/
class Address
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// ...
}
Why is "mappedBy" required if the association is unidirectional? Thanks in advance.
UPDATE: just as mentioned in the comment by @tchap an unidirectional OneToMany can be mapped with a @ManyToMany and a unique constraint on one of the join columns to enforce the onetomany cardinality. Just as the documentation says, but it was a bit confusing for me because there is already a @OneToMay annotation. So I just have to change the above code to this (by only changing the @OneToMany to @ManyToMany):
/**
* @ORM\ManyToMany(targetEntity="Address")
* @ORM\JoinTable(name="users_address",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="address_id", referencedColumnName="id", unique=true)}
* )
*/
private $address;
A OneToMany
has to be bi-directional and is always the inverse side of a relationship and if you define the inverse side you need to point at the owning side of the relationship with a mappedBy
attribute. The owning side is ManyToOne
. In your case this would look like this:
In User
your association has a mappedBy="user"
attribute and points to the owning side Address
:
/** ONE-TO-MANY BIDIRECTIONAL, INVERSE SIDE
* @var Collection
* @ORM\OneToMany(targetEntity="Address", mappedBy="user")
*/
protected $addresses;
In Address
your association has a inversedBy="addresses"
attribute and points to the inverse side User
:
/** MANY-TO-ONE BIDIRECTIONAL, OWNING SIDE
* @var User
* @ORM\ManyToOne(targetEntity="User", inversedBy="addresses")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
The advantage of this solution is that you can find which user owns the Address
by doing: $address->getUser();
and that you skip adding an additional join table to your database.
If you want the relationship to be uni-directional you can do as you did in your update; define a ManyToMany
relationship with a join table and add a unique constraint on the address_id
column.
/**
* @ORM\ManyToMany(targetEntity="Address")
* @ORM\JoinTable(name="user_address",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="address_id", referencedColumnName="id", unique=true)}
* )
*/
The disadvantage of this solution is that you cannot find out which User
owns the address from the Address
resource (the Address
is not aware of the User
). Such example can also be found here in the Doctrine documentation chapter 5.6. One-To-Many, Unidirectional with Join Table.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With