title: Custom Fields in Doctrine MongoDB Document
body: <p>I have a specific requirement in a project that requires the use of <code>MongoDB Collection</code>, that contains <code>Documents</code> with different field sets.</p>
  
  <p>For example, these two <code>Documents</code> are in the same Collection. The <code>name</code> and <code>foo</code> fields are mandatory.</p>
  
  <pre><code>{ 'name': 'scott', 'foo': 'abc123' }
  { 'name': 'jack' , 'foo': 'def456', 'bar': 'baz' }
  </code></pre>
  
  <p>Using Doctrine MongoDB ODM, the <code>Document</code> fields would be specified in a <code>Document</code> class.</p>
  
  <p>As for now, I have my <code>Document</code> class extending the following <code>BaseDocument</code> and created a custom listener for <code>PostPersist</code> event, to update the persisted <code>Document</code> with the custom fields.</p>
  
  <p><code>BaseDocument</code> class:</p>
  
  <pre><code>class BaseDocument
  {
      protected $customFields;
  
      public function __construct()
      {
          $this-&gt;customFields = array();
      }
  
      public function setCustomField($name, $value)
      {
          if (\property_exists($this, $name)) {
              throw new \InvalidArgumentException("Object property '$name' exists, can't be assigned to a custom field");
          }
          $this-&gt;customFields[$name] = $value;
      }
  
      public function getCustomField($name)
      {
          if (\array_key_exists($name, $this-&gt;customFields)) {
              return $this-&gt;customFields[$name];
          }
  
          throw new \InvalidArgumentException("Custom field '$name' does not exists");
      }
  
      public function getCustomFields()
      {
          return $this-&gt;customFields;
      }
  }
  </code></pre>
  
  <p><code>postPersist</code> listener:</p>
  
  <pre><code>class CustomFieldListener
  {
      public function postPersist(LifecycleEventArgs $args)
      {   
          $dm = $args-&gt;getDocumentManager();
          $document = $args-&gt;getDocument();
  
          $collection = $dm-&gt;getDocumentCollection(\get_class($document));
          $criteria = array('_id' =&gt; new \MongoID($document-&gt;getId()));
          $mongoDoc = $collection-&gt;findOne($criteria);
          $mongoDoc = \array_merge($mongoDoc, $document-&gt;getCustomFields());;
          $collection-&gt;update($criteria, $mongoDoc);
      } 
  }
  </code></pre>
  
  <p>The current solution is not elegant at all, and requires both <code>insert</code> and <code>update</code> calls to insert a single <code>Document</code>. What is the better way to inject custom fields into the <code>Document</code> when persisting, reading &amp; updating?</p>