Sunday, January 17, 2016

Uniqueness Validation for Entity Collection - Symfony2

Sometimes it is necessary to maintain the uniqueness of a field across the entities. For example you may want the email address to be unique across all the users throughout a Symfony2 application. For this, you can simply use the Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity.

But consider the case where you want to persist a collection of entities at once. You want a particular field of these entities to be unique. Will the above mentioned UniqueEntity constraint work in this scenario? Well, the answer is "No". UniqueEntity checks the uniqueness of the new value against the values which are already persisted. In our case, the uniqueness has to be validated across the entities which are not yet persisted.

Consider the following example where the uniqueField is the unique field across all the MyEntity entities. Suppose you are saving a collection of MyEntity's at once. Now you want  all the uniqueField values to be different from each other, and they also must not have the same values as the already persisted values.

First add the constraint class.

1:  <?php  
2:  namespace MyBundle\Validator\Constraint;  
3:  use Symfony\Component\Validator\Constraint;  
4:  /**  
5:   *  
6:   * @Annotation  
7:   */  
8:  class UniqueInCollection extends Constraint {  
9:    public $message = 'This value has been already entered above.';  
10:    // The property path used to check wether objects are equal  
11:    // If none is specified, it will check that objects are equal  
12:    public $propertyPath = null;  
13:  }  

Then add the constraint validator class.

1:  <?php  
2:  namespace MyBundle\Validator\Constraint;  
3:  use Symfony\Component\Validator\Constraint;  
4:  use Symfony\Component\Validator\ConstraintValidator;  
5:  use Symfony\Component\Form\Util\PropertyPath;  
6:  /**  
7:   * Description of UniqueInCollectionValidator  
8:   *  
9:   * @author sahan  
10:   */  
11:  class UniqueInCollectionValidator extends ConstraintValidator {  
12:    private $collectionValues = array();  
13:    public function validate($value, Constraint $constraint) {  
14:      // Apply the property path if specified  
15:      if ($constraint->propertyPath) {  
16:        $propertyPath = new PropertyPath($constraint->propertyPath);  
17:        $value = $propertyPath->getValue($value);  
18:      }  
19:      // Check that the value is not in the array  
20:      if (in_array($value, $this->collectionValues))  
21:        $this->context->addViolation($constraint->message, array());  
22:      // Add the value in the array for next items validation  
23:      $this->collectionValues[] = $value;  
24:    }  
25:  }  

Now you are ready to go. You can use this validator in your validation file. In my case, I will go ahead with YAML.

1:  MyBundle\Entity\MyEntity:  
2:    constraints:  
3:      # validates across existing entities  
4:      - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity: uniqueField  
5:    properties:  
6:      uniqueField:  
7:        # validates across the entity collection  
8:        - MyBundle\Validator\Constraint\UniqueInCollection: ~  

This validator will attach the validation message (in case it is invalid) to the uniqueField property.

References:
http://stackoverflow.com/questions/11782056/how-to-validate-unique-entities-in-an-entity-collection-in-symfony2

Saturday, January 16, 2016

Core Concepts behind an ORM

This article explains the core functionalities and some key features of an object-relational mapping (ORM) framework working through some simple examples. For these examples, we use Doctrine 2 as the example ORM.

Introduction

First of all, let us discuss the reason we need an ORM to develop our application. What are the benefits of an ORM? As developers, we often work and deal with objects. In the traditional database world, however, these data are maintained as table records (relational databases). A developer prefers working with these data in an object level rather than in the underlying record level. An ORM will work in the middle as a mapper between these two layers.

Association Mapping

When we work in the database level, how do we manage the relationships among objects? (From now on, we will use the word entity to refer to an object.) We will use the following example to take you through this explanation.

Example 1:

A customer can place as many orders as he wants, but an order cannot be shared among multiple customers. So the relationship is a one-to-many relationship, where the "many side" is the order.

Inner Workings

The ORM (in this case, Doctrine 2) will, maintain a table for each of your entities, map each field of your entity to a column of the respective table. Things become more interesting when it comes to holding the associations among different entities. Fundamentally, there can be two types of associations.
  1. Reference to a single entity is maintained using a foreign key.
  2. Reference to a collection of entities is maintained by keeping the foreign key to the holding entity, in each of the entities in the collection. (This is further explained below.)

Owning and Inverse Sides of an Association

To put in a nutshell, owning side is the side of the relationship, we prefer to deal with (We choose that side, so that we can look at the relationship form its perspective more easily.) Consider the customer-order example above. In the business world, our natural instinct suggests that, the Customer is the owning side of the association. In other words, the customer owns the order(s).

But in the database world, it is the other way around. Rather than keeping a pointer inside the Customer to each and every order he has placed, it is more convincing to keep a single pointer inside each and every order, to the customer who owns it. (Yes, that is what is done the database management systems. You will keep the foreign key in the Order table, not the other way around!)

So here, the owning side is the Order, and the inverse side is the Customer. In one-to-many associations, this is often the case. However in one-to-one and many--to-many types, it is up to you to decide on the owning side of the association (and yes, you have to figure out from which entity's perspective you are going to look at the association).

Example 2:

Consider the example of the article-tag relationship. There can be multiple articles under the same tag, and there can be multiple tags attached to a single article. So, do you want to get the articles under a particular tag, or do you want to get the tags attached to a particular article? It is totally up to you.

Note:

The bottom line is, when you are dealing with the owning entity of an association, the relationship is handled by the framework. However if you want to deal with inverse side, you will need some workaround to get things working.

The use of ORM frameworks have become popular in web and mobile solution development. Java's Hibernate is the biggest competitor around. Doctrine 2 for PHP, OrmLite for Android are some other popular object-relational frameworks.