title: Symfony2 forms: How do I persist an entity with a nullable association?
body: <p>When saving form submission data, I'm having trouble persisting a new entity instance where the entity has a nullable association with another entity and I attempt to set it to null.  After creating a new entity instance for the form, binding the submitted request to the form and persisting and flushing the entity instance, depending on how I populate the property for the associated entity, I either get </p>
  
  <ol>
  <li><code>UnexpectedTypeException: Expected argument of type "object or array", "NULL" given</code> (if set to null), or</li>
  <li><code>InvalidArgumentException: A new entity was found through the relationship 'AccessLog#document' that was not configured to cascade persist operations for entity</code> (if set to a new, empty instance of the related entity, which I don't want to persist).</li>
  </ol>
  
  <p>If I set up cascade persist, it tries to create a record in the related table (which is not allowed by the data model in the db), even though there's no data for it to persist.  If setting up cascade persist is the way to go, how do I prevent it from trying to create a new record?  What's the best way to handle this?</p>
  
  <p>Note, the behavior is the same whether the association is set up as unidirectional or bidirectional.</p>
  
  <p><strong>Details:</strong></p>
  
  <p>I have an entity with a many-to-one association with another entity (abbreviated):</p>
  
  <pre><code>/** @Entity */
  class AccessLog
  {
      /** @Id @Column(type="integer") */
      private $access_log_id;
  
      /** @Column(type="integer", nullable=true) */
      private $document_id;
  
      /**
       * @ManyToOne(targetEntity="Document", inversedBy="access_logs", cascade={"persist"})
       * @JoinColumn(name="document_id", referencedColumnName="document_id")
       */
      private $document;
  
      // plus other fields
      // plus getters and setters for all of the above...
  }
  </code></pre>
  
  <p>The related entity is nothing fancy:</p>
  
  <pre><code>/** @Entity */
  class Document
  {
      /** @Id @Column(type="integer") */
      private $document_id;
  
      /** @Column(length=255) */
      private $name;
  
      /** @OneToMany(targetEntity="AccessLog", mappedBy="document") */
      private $access_logs;
  
      // plus other fields
      // plus getters and setters for all of the above...
  }
  </code></pre>
  
  <p>I have a Symfony form for entering data for new AccessLog records:</p>
  
  <pre><code>class AccessLogFormType extends AbstractType
  {
      public function getName()
      {
          return 'access_log_form';
      }
  
      public function getDefaultOptions(array $options)
      {
          return array('data_class' =&gt; 'AccessLog');
      }
  
      public function buildForm(FormBuilder $builder, array $options)
      {
          $builder-&gt;add('access_log_id', 'hidden');
          $builder-&gt;add('document_id', 'hidden', array(
              'required' =&gt; false
          ));
          $builder-&gt;add('document', new DocumentType(), array(
              'label' =&gt; 'Document',
              'required' =&gt; false
          ));
          //...
      }
  }
  </code></pre>
  
  <p>With the following supporting type definition:</p>
  
  <pre><code>class DocumentType extends AbstractType
  {
      public function getName()
      {
          return 'document';
      }
  
      public function getDefaultOptions(array $options)
      {
          return array('data_class' =&gt; 'Document');
      }
  
      public function buildForm(FormBuilder $builder, array $options)
      {
          $builder-&gt;add('name', 'text', array(
              'required' =&gt; false
          ));
      }
  }
  </code></pre>
  
  <p>My controller includes the following:</p>
  
  <pre><code>public function save_access_log_action()
  {
      $request = $this-&gt;get('request');
      $em = $this-&gt;get('doctrine.orm')-&gt;getEntityManager();
  
      $access_log = null;
  
      if ($request-&gt;getMethod() === 'POST') {
          $data = $request-&gt;request-&gt;get('access_log_form');
  
          if (is_numeric($data['access_log_id'])) {
              $access_log = $em-&gt;find('AccessLog', $data['access_log_id']);
          } else {
              $access_log = new AccessLog();
          }
  
          if (is_numeric($data['document_id'])) {
              $document = $em-&gt;find('Document', $data['document_id']);
              $access_log-&gt;set_document($document);
  
          } else {
              // Not calling set_document() since there shouldn't be a
              // related Document entity.
          }
  
          $form = $this-&gt;get('form.factory')
              -&gt;createBuilder(new AccessLogFormType(), $access_log)
              -&gt;getForm();
  
          $form-&gt;bindRequest($request);
  
          if ($form-&gt;isValid()) {
              $em-&gt;persist($access_log);
              $em-&gt;flush();
          }
  
      } else {
          // ... (handle get request)
      }
  
      return $this-&gt;render('access_log_form.tpl', array(
          'form' =&gt; $form-&gt;createView()
      ));
  }
  </code></pre>
  
  <p>The above code works fine when updating an existing access log entry or creating a new one and a document is selected in the form, but not if no document is selected.</p>
  
  <p>Assuming the data model cannot be changed, how do I go about persisting a new AccessLog entity without persisting a new Document entity?</p>