Symfony2 + Doctrine2: Entity Removal with Collections
<p><strong>Background Info</strong></p>

<p>I have an entity called AnnualReport with multiple collections (let's say 2 for brevity's sake). Removal of <strong>one of these collections is handled automatically</strong> in the FormType:</p>

<pre><code>        //AnnualReportStaffing entity collection
        -&gt;add('staffingTenured', 'collection', array(
            'type' =&gt; new AnnualReportStaffingType(),
            'allow_add' =&gt; true,
            'allow_delete' =&gt; true,
            'by_reference' =&gt; false,
        ))
</code></pre>

<p>The <strong>other collection</strong> is a collection of files and deletion <strong>is NOT handled automatically</strong>:</p>

<pre><code>        //AnnualReportDetail entity collection
        -&gt;add('documents', 'collection', array(
            'type' =&gt; new AnnualReportDocumentType(),
            'allow_add' =&gt; true,
            'allow_delete' =&gt; false, // Do NOT automatically remove documents not in the collection (i.e. edit form where Documents are not passed again)
            'by_reference' =&gt; false,
        ))
</code></pre>

<p>This is the property/method declaration of each collection within my AnnualReport entity class:</p>

<pre><code>/**
 * @ORM\ManyToMany(targetEntity="AnnualReportStaffing", cascade={"persist", "detach", "remove"}, orphanRemoval=true, fetch="LAZY")
 * @ORM\JoinTable(name="annualreports_staffingtenure",
 *      joinColumns={@ORM\JoinColumn(name="annualreport_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="staffing_id", referencedColumnName="id", onDelete="CASCADE")},
 *      )
 */
private $staffingTenured;

/**
 * @ORM\ManyToMany(targetEntity="Document", cascade={"persist", "detach", "remove"}, orphanRemoval=true, fetch="LAZY")
 * @ORM\JoinTable(name="annualreports_documents",
 *      joinColumns={@ORM\JoinColumn(name="annualreport_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="document_id", referencedColumnName="id", onDelete="CASCADE")},
 *      )
 */
private $documents;

public function __construct(AnnualReportUnit $unit, $year) {
    $this-&gt;staffingTenured = new ArrayCollection();
    $this-&gt;documents = new ArrayCollection();
}

/**
 * Add staffingTenured
 *
 * @param AppBundle\Entity\AnnualReportStaffing  $staffing
 * @return AnnualReport
 */
public function addStaffingTenured(AnnualReportStaffing $staffing)
{
    $this-&gt;staffingTenured-&gt;add($staffing);

    return $this;
}

/**
 * Remove staffingTenured
 *
 * @param AppBundle\Entity\AnnualReportStaffing  $staffing
 * @return AnnualReport
 */
public function removeStaffingTenured(AnnualReportStaffing $staffing)
{
    $this-&gt;staffingTenured-&gt;removeElement($staffing);

    return $this;
}

/**
 * Get staffingTenured
 *
 * @return ArrayCollection 
 */
public function getStaffingTenured()
{
    return $this-&gt;staffingTenured;
}

/**
 * Add document
 *
 * @param AppBundle\Entity\AnnualReportDocument  $document
 * @return AnnualReport
 */
public function addDocument(AnnualReportDocument $document)
{
    $this-&gt;documents-&gt;add($document);

    return $this;
}

/**
 * Remove document
 *
 * @param AppBundle\Entity\AnnualReportDocument  $document
 * @return AnnualReport
 */
public function removeDocument(AnnualReportDocument $document)
{
    $this-&gt;documents-&gt;removeElement($document);

    return $this;
}

/**
 * Get documents
 *
 * @return ArrayCollection
 */
public function getDocuments()
{
    return $this-&gt;documents;
}
</code></pre>

<p><strong>Problem</strong></p>

<p>When it comes time to delete an AnnualReport entity:</p>

<ul>
<li>If documents are present, I am able to delete the documents collection, but I get a Foreign key constraint error about the staffingTenured items.</li>
</ul>

<blockquote>
<pre><code>An exception occurred while executing 'DELETE FROM annual_report WHERE id = ?' with params [57]:

SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails
</code></pre>
  
  <p>(<code>libcommand</code>.<code>annualreports_staffingtenure</code>, CONSTRAINT
  <code>FK_DB56517AD4F67A27</code> FOREIGN KEY (<code>annualreport_id</code>) REFERENCES
  <code>annual_report</code> (<code>id</code>))</p>
</blockquote>

<ul>
<li>If NO documents are present, the AnnualReport entity and all staffingTenured items are removed as expected.</li>
</ul>

<p>This is the deleteAction():</p>

<pre><code>public function deleteAction(Request $request, $id)
{
    $requestData = $request-&gt;request-&gt;all();
    $unit = $requestData['form']['unit'];


    $form = $this-&gt;createDeleteForm($id);
    $form-&gt;handleRequest($request);

    if ($form-&gt;isValid()) {
        $em = $this-&gt;getDoctrine()-&gt;getManager();
        $entity = $em-&gt;getRepository('AppBundle:AnnualReport')-&gt;find($id);

        if (!$entity) {
            throw $this-&gt;createNotFoundException('Unable to find AnnualReport entity.');
        }

        //Remove any documents (allow_delete set to FALSE in form so have to do manually)
        $documents = $entity-&gt;getDocuments();
        foreach($documents as $document){
            $entity-&gt;removeDocument($document);
            //$em-&gt;remove($document);
        }
        $em-&gt;persist($entity);
        $em-&gt;flush();

        $em-&gt;remove($entity);
        $em-&gt;flush(); //flush again to remove the annual report
    }

    return $this-&gt;redirect($this-&gt;generateUrl('annualreportunit_edit', array('id' =&gt; $unit)));
}
</code></pre>