Molarro
Molarro

Reputation: 1047

Understanding of “owning side” and “inverse side” concepts in Doctrine

Please, could anybody explain with examples idea of “owning side” and “inverse side” concepts in Doctrine? I understand that they are necessary to organize bidirectional relationship, but I can’t realize following text from Doctrine documentation (link):

There are 2 references on each side of the association and these 2 references both represent the same association but can change independently of one another.

  1. Why there are 2 references on each side, and in total 4? Now, in total, I see only 2 references From A (owning side) to B (inverse side), and from B to A.
  2. In which situations references can be changed independently of one another?
  3. What happens in memory that trigger necessity of “owning side ” and “ inverse side usage?
  4. What is difference between “reference” and “association”?

Edit
For example, I have entities Customer (owning side) and Company (inverse side). At first, I do following:

$customer = new  Customer(); 
$company = new Company();
$customer->setCompany($company);
$company->setCustomer($customer);

Then I can have two scenarios:

Scenario 1

$company->getCustomer()->setName(‘John’);
$entityManager->persist($company);
$entityManager->flush();

Scenario 2

$customer->getCompany()->setLicenseNumber(‘24535’);
$entityManager->persist($company);
$entityManager->flush();

Do I understand rightly, that in first case association will be persisted correctly, because owning side (through getCustomer()) is changed, but in second case it will be ignored, because owning side is not changed?

Upvotes: 1

Views: 1220

Answers (1)

Wilt
Wilt

Reputation: 44316

  1. You should read as: There are 2 references, one on each side of the association
    So there are not 4 but 2...
  2. in a correct application the semantics of the bidirectional association are properly maintained by the application developer
    In other words they can, but should not if you correctly implement the relationship.
  3. Changes made only to the inverse side of an association are ignored.
    So in principle (for keeping your database model up to date) only maintaining the owning side would suffice, but in your object model you would (maybe) like to access your associations from the inverse side as well and when you access the inverse side you want the values (for example an array collection on inverse side) to be correct, that is why you should take care of both sides.
  4. I think something like this: the association is the actual relationship, references are like the handles to this relationship.

I tried to add quotes from the documentation to my answer. Please leave a comment if you/someone does not agree with my answer or if you see a possibility to improve the explanations...

UPDATE:

Example for your Company and User...

Customer entity:

class Customer
{
    // ...

    /** ONE-TO-ONE BIDIRECTIONAL, OWNING SIDE
     * @ORM\OneToOne(targetEntity="Company", inversedBy="customer")
     * @ORM\JoinColumn(name="company_id", referencedColumnName="id")
     */
    private $company;

    // ...

    /**
     * Set company method
     *
     * @param Company $company
     */
    public function setCompany( Company $company )
    {
       $this->company = $company; 
       $company->setCustomer( $this );
    }
}

Company entity:

class Company
{
    // ...

    /** ONE-TO-ONE BIDIRECTIONAL, INVERSE SIDE
     * @OneToOne(targetEntity="Customer", mappedBy="company")
     */
    private $customer;

    // ...
}

An example:

$company= $em->find('Application\Entity\Company', 1);
$customer = $em->find('Application\Entity\Customer', 1);

$customer->setCompany($company);
$em->persist($customer);
$em->flush();

If you now do $customer = $company->getCustomer(); you will get a Customer with id 1.

And now imagine not having the line $company->setCustomer( $this ); in the setCompany method. If you then do $customer = $company->getCustomer(); after setting $company you will not get a Customer with id 1. In other words the association on inverse side does not correspond with your database model and does not correspond with the reference on the owning side.

Upvotes: 1

Related Questions