otporan
otporan

Reputation: 1355

Doctrine - OneToOne Unidirectional vs OneToOne Bidirectional

I joust started playing around with Doctrine ORM library, and Im learning about all associations between tables.

So Im stuck with differences in Unidirectional and Bidirectional relation.

As I get it, Unidirectional relation has primary key only on one side, and that side is owning side right? And Bidirectional relation have primary key in both tables and therefore you can have relation from both sides, and set constrains on both sides.

Now, Im reading through Doctrine documentation about relations and there you have: Unidirectional and Bidirectional associations.

But they produce the same SQL, and the same tables with the same primary key-s and constrains. So I dont really see any difference in those two. And both examples have primary key on one side.

As I get it the true Bidirectional relation should have primary keys in both tables pointing to the other table right? And with given example on Doctrine documentation that is not the case. Both examples give the same result and are the same.

So what I did, is this, lets say I have User and Card Entity, and want relation to be OneToOne Bidirectional.

    /**
 * @Entity
 * @Table(name="users")
 */

class User
{
    /**
     * @Id
     * @GeneratedValue
     * @Column(type="bigint")
     */
    protected $id;

    /**
     * @OneToOne(targetEntity="Card", mappedBy="User")
     * @JoinColumn(name="card_id", referencedColumnName="id")
     */
    protected $card;

    /**
     * @Column(name="user_name", type="string")
     */
    protected $userName;

    /**
     * @Column(name="user_pass", type="string")
     */
    protected $userPass;
}

    /**
 * @Entity
 * @Table(name="cards")
 */

class Card
{
    /**
     * @Id
     * @GeneratedValue
     * @Column(type="bigint")
     */
    protected $id;

    /**
     * @OneToOne(targetEntity="User", inversedBy="Card")
     * @JoinColumn(name="user_id", referencedColumnName="id")
     */
    protected $user;

    /**
     * @Column(name="post_title", type="string")
     */
    protected $cardType;
}

The difference here is I wrote @JoinColumn in both objects/entities. And in Doctrine example there is only one. Now I would get what I think is Bidirectional relation. If i look at EER diagram, I can see one line pointing from user to card, and the other from card to user.

So basicly did I get this right? Is the Doctrine documentation wrong? :D How would Bidirectional OneToOne relation look in EER diagram?

Thanks!

Upvotes: 21

Views: 12049

Answers (2)

radkovo
radkovo

Reputation: 888

The only difference is in the PHP class interface, i.e. in the presence or absence of the property that points back to the owner (e.g. the $customer property in the mentioned Doctrine example). In other words Doctrine just needs to know whether it should take care about a single property ($shipping) or two properties ($cart and $customer). There is no other difference. Therefore, the SQL code is the same (because one foreign key is sufficient for representing any 1:N relationship) and there would no difference in EER diagram neither (because in EER you typically do not solve such PHP-related implementation details).

Upvotes: 20

Criss
Criss

Reputation: 1211

Unidirectional and bidirectional have nothing to do with the background algorithm how to create these connections in the database layer.

All they talk about is how the connections can be used. In an unidirectional relationship you can access the target only from one site. An bidirectional relationship allows the connection to be called from two (both) sides.

So in an unidir. rel. model_a can get to model_b, but model_b cant get to model_a (without extra work). If you now use a bidir. rel both models can access each other without problems

In doctrine terms, a unidirectional relationship defines a $modelA->getModelB() method, but not a $modelB->getModelA() method, whereas a bidirectional relationship defines both methods (or accessors, however you want to call them)

in an uml diagram it would look like this:

unidirectional
modelA --X------> modelB

bidirectional
modelA <--------> modelB

Upvotes: 12

Related Questions