Doctrine mapping (ORM) with Database (DAL), Unidirectional vs Bidirectional.

Creating relationships inside a database is a very common thing for an web developer. Respecting to to RDBMS concept, we can create any sort of relationship inside a database. Things get changed when we have to use Doctrine for the mapping with database. Initially this made pretty much confused to me. Only after live working examples and few docs, I could able to get rid of it somehow. This post is about Doctrine mapping and difference between Unidirectional and Bidirectional relationship.

What is Doctrine ?
Doctrine is a set of PHP libraries that provides persistence services that is helpful managing PHP objects with Database layer. That means it creates a bridge between PHP light weight mapped objects and Database Objects. So Doctrine provides how to map PHP objects internally by its ORM (Object Relational Mapper) and its DB layer (DAL : Database Abstraction Layer) provides a unique object based query language(DQL : Doctrine Query Language) to write db queries independent of database type.

Mapping :
In any relationship a foreign key plays the key role. Hence its important which table hosts the foreign key. ORM works with pretty same logic, besides it also asks, if we want other side to deal with its parent data populated when object gets persisted/fetched that is where the type of relationship comes into consideration. An example could make it clearer.

Example :
An Author and his written books could be a good example. where book table must host author_id, creating a many-to-one relationship with Author table.

Unidirectional or Bidirectional ?
Often we get confused which relationship we should follow. Its simple to choose. If both PHP objects(Author and Book) need to reflect/persist each others related object info, go for Bidirectional else Unidirectional. This is important to know database structure doesn't change in either of these cases, only our PHP objects does the trick on PHP end.

In Unidirectional relationship, you can access the data from one side whereas in Bidirectional relationship you can access data from both end.

A simple Unidirectional ORM mapping in xml from Book entity would look like this :
1
2
3
4
5
<many-to-one field="author" target-entity="Author">
    <join-columns>
        <join-column name="author_id" referenced-column-name="id"/>
    </join-columns>
</many-to-one>

A simple Bidirectional ORM mapping in xml format.
From Book entity With many-to-one targeting Author :
1
2
3
4
5
<many-to-one field="author" target-entity="Author" inversed-by="books">
    <join-columns>
        <join-column name="author_id" referenced-column-name="id"/>
    </join-columns>
</many-to-one>

As you see here we have added inversed-by property along with target Entity, which means this mapping has another reference property called 'books' inside Author Entity that is mapped back to this Entity.

Now here is how a Author Entity mapping should look like :

1
<one-to-many field="books" target-entity="Book" mapped-by="author" />

Here we don't have to provide Join column (foreign key) information as its already setup inside Book entity. we just have to mention the mapped-by tag that should be referenced back to 'author' field mapping in Book entity.

Note : inversed-by must be placed on Many side of a relationship, normally the entity that stores the foreign key.

Hope it helps! I will improvise this post sooner to correct any missing info.


Comments

Popular posts from this blog

Filtering and Sorting a Doctrine Arraycollection

Symfony 2 How to keep cloned entity properties unchanged on change of main entity.