title: Removing the jointable entry only in a Doctrine ManyToMany
body: <p>I can't get my head around this:</p>
  
  <p>I followed the symfony cookbook example explaining how to deal with arraycollections in symfony forms: <a href="http://symfony.com/doc/current/form/form_collections.html" rel="nofollow noreferrer">link</a></p>
  
  <p>I only changed "tasks" and "tags" by "gigs" and "artists".
  It all works fine, i can add artists to gigs, the resulting join-table looks fine.
  but when it comes to deleting an artist, doctrine not tries to delete the join-table entry as intended, but tries to set the artist name to null which is not not working and wrong anyway. i want to keep the artist, but delete the relation to the gig.
  therefore i managed the persisting myself and didn't user persist{"cascade"}..</p>
  
  <p>what am i doing wrong?</p>
  
  <p>i hope, my question is formed well enough and i provided enough information. i tried to search for this issue but couldn't find a solution.</p>
  
  <p>thank you</p>
  
  <p>just</p>
  
  <p>error:</p>
  
  <blockquote>
    <p>An exception occurred while executing 'UPDATE artist SET name = ? WHERE id = >?' with params [null, 10]:</p>
    
    <p>SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'name' cannot >be null </p>
  </blockquote>
  
  <p>gig.php:</p>
  
  <pre><code>/**
   * @var \Doctrine\Common\Collections\ArrayCollection|Artist[]
   *
   * @ORM\ManyToMany(targetEntity="GoetzBundle\Entity\Artist", inversedBy="gigs"), 
   * @ORM\JoinTable(name="gigs_artits")
   */
  private $artists;
  
  ...
  
   /**
   * @return ArrayCollection|Artist
   */
  public function getArtists()
  {
      return $this-&gt;artists;
  }
  
  /**
   * @param Artist $artist
   * @return ArrayCollection|Artist
   */
  public function addArtist($artist)
  {
      $artist-&gt;addGig($this);
      $this-&gt;artists-&gt;add($artist);
  
      return $this-&gt;artists;
  }
  
  /**
   * @param Artist $artist
   * @return ArrayCollection|Artist
   */
  public function removeArtist($artist)
  {
      $artist-&gt;removeGig($this);
      $this-&gt;artists-&gt;removeElement($artist);
  
      return $this-&gt;artists;
  }
  </code></pre>
  
  <p>artist.php</p>
  
  <pre><code>/**
   * @var \Doctrine\Common\Collections\ArrayCollection|Gig[]
   *
   * @ORM\ManyToMany(targetEntity="GoetzBundle\Entity\Gig", mappedBy="artists", fetch="EAGER")
   *
   */
  private $gigs;
  
  ...
  
  /**
   * @param Gig $gig
   * @return ArrayCollection|Gig
   */
  public function addGig(Gig $gig)
  {
      if (!$this-&gt;gigs-&gt;contains($gig)) {
          $this-&gt;gigs-&gt;add($gig);
      }
      return $this-&gt;gigs;
  }
  
  /**
   * @param Gig $gig
   * @return ArrayCollection|Gig
   */
  public function removeGig(Gig $gig)
  {
      if ($this-&gt;gigs-&gt;contains($gig)) {
          $this-&gt;gigs-&gt;removeElement($gig);
      }
      return $this-&gt;gigs;
  }
  </code></pre>
  
  <p>gigtype.php</p>
  
  <pre><code>...
  
  $builder
          -&gt;add('artists', CollectionType::class, array(
              'entry_type' =&gt; ArtistType::class,
              'allow_add' =&gt; true,
              'by_reference' =&gt; false,
              'allow_delete' =&gt; true,
          ))
  
  ...
  </code></pre>
  
  <p>gigcontroller.php</p>
  
  <pre><code>public function newAction(Request $request)
  {
      $gig = new Gig();
  
      $form = $this-&gt;createForm('GoetzBundle\Form\GigType', $gig);
      $form-&gt;handleRequest($request);
  
      if ($form-&gt;isSubmitted() &amp;&amp; $form-&gt;isValid()) {
          $em = $this-&gt;getDoctrine()-&gt;getManager();
  
          foreach ($gig-&gt;getArtists() as $artist){
              $em-&gt;persist($artist);
          }
  
          $em-&gt;persist($gig);
          $em-&gt;flush();
  
          return $this-&gt;redirectToRoute('gig_show', array('id' =&gt; $gig-&gt;getId()));
      }
  
      return $this-&gt;render('@Goetz/gig/new.html.twig', array(
          'gig' =&gt; $gig,
          'form' =&gt; $form-&gt;createView(),
      ));
  }
  
  ...
  
  public function editAction(Request $request, Gig $gig)
      {
          $deleteForm = $this-&gt;createDeleteForm($gig);
  
          $em = $this-&gt;getDoctrine()-&gt;getManager();
          $gig = $em-&gt;getRepository('GoetzBundle:Gig')-&gt;find($gig);
  
          $originalArtists = new ArrayCollection();
  
          foreach ($gig-&gt;getArtists() as $artist){
              $originalArtists-&gt;add($artist);
          }
  
          $editForm = $this-&gt;createForm('GoetzBundle\Form\GigType', $gig);
          $editForm-&gt;handleRequest($request);
  
          if ($editForm-&gt;isSubmitted() &amp;&amp; $editForm-&gt;isValid()) {
  
              foreach ($originalArtists as $artist){
                  if (false === $gig-&gt;getArtists()-&gt;contains($artist)){
                      $artist-&gt;getGigs()-&gt;removeElement($gig);
                  }
                  $em-&gt;persist($artist);
              }
  
              $em = $this-&gt;getDoctrine()-&gt;getManager();
  
              foreach ($gig-&gt;getArtists() as $artist){
                  $em-&gt;persist($artist);
              }
  
              $em-&gt;persist($gig);
              $em-&gt;flush();
  
              return $this-&gt;redirectToRoute('gig_edit', array('id' =&gt; $gig-&gt;getId()));
          }
  
          return $this-&gt;render('Goetz/gig/edit.html.twig', array(
              'gig' =&gt; $gig,
              'edit_form' =&gt; $editForm-&gt;createView(),
              'delete_form' =&gt; $deleteForm-&gt;createView(),
          ));
      }
  </code></pre>
  
  <p>edit.html.twig</p>
  
  <pre><code>{% block content %}
      &lt;h1&gt;Gig edit&lt;/h1&gt;
  
      {{ form_start(edit_form) }}
      &lt;h3&gt;Artists&lt;/h3&gt;
      &lt;ul class="artists" data-prototype="{{ form_widget(edit_form.artists.vars.prototype)|e('html_attr') }}"&gt;
          {% for artist in edit_form.artists %}
              &lt;li&gt;{{ form_row(artist.name) }}&lt;/li&gt;
          {% endfor %}
      &lt;/ul&gt;
          {{ form_rest(edit_form) }}
          &lt;input type="submit" value="Edit" /&gt;
      {{ form_end(edit_form) }}
  
      &lt;ul&gt;
          &lt;li&gt;
              &lt;a href="{{ path('gig_index') }}"&gt;Back to the list&lt;/a&gt;
          &lt;/li&gt;
          &lt;li&gt;
              {{ form_start(delete_form) }}
                  &lt;input type="submit" value="Delete"&gt;
              {{ form_end(delete_form) }}
          &lt;/li&gt;
      &lt;/ul&gt;
  {% endblock %}
  {% block javascripts %}
      {{ parent() }}
      &lt;script type="text/javascript" src="{{ asset('bundles/goetz/js/artists.js') }}"&gt;&lt;/script&gt;
  {% endblock %}
  </code></pre>
  
  <p>(new looks the same)</p>
  
  <p>artists.js</p>
  
  <pre><code>var $collectionHolder;
  
  // setup an "add a artist" link
  var $addArtistLink = $('&lt;a href="#" class="add_tag_link"&gt;Künstler hinzufügen&lt;/a&gt;');
  var $newLinkLi = $('&lt;li&gt;&lt;/li&gt;').append($addArtistLink);
  
  jQuery(document).ready(function() {
      // Get the ul that holds the collection of artists
      $collectionHolder = $('ul.artists');
  
      $collectionHolder.find('li').each(function() {
          addArtistFormDeleteLink($(this));
      });
  
  
      // add the "add a artist" anchor and li to the artists ul
      $collectionHolder.append($newLinkLi);
  
  
      // count the current form inputs we have (e.g. 2), use that as the new
      // index when inserting a new item (e.g. 2)
      $collectionHolder.data('index', $collectionHolder.find(':input').length);
  
      $addArtistLink.on('click', function(e) {
          // prevent the link from creating a "#" on the URL
          e.preventDefault();
  
          // add a new artist form (see next code block)
          addArtistForm($collectionHolder, $newLinkLi);
      });
  });
  
  function addArtistForm($collectionHolder, $newLinkLi) {
      // Get the data-prototype explained earlier
      var prototype = $collectionHolder.data('prototype');
  
      // get the new index
      var index = $collectionHolder.data('index');
  
      // Replace '__name__' in the prototype's HTML to
      // instead be a number based on how many items we have
      var newForm = prototype.replace(/__name__/g, index);
  
      // increase the index with one for the next item
      $collectionHolder.data('index', index + 1);
  
      // Display the form in the page in an li, before the "Add a artist" link li
      var $newFormLi = $('&lt;li&gt;&lt;/li&gt;').append(newForm);
      $newLinkLi.before($newFormLi);
      addArtistFormDeleteLink($newFormLi);
  }
  
  function addArtistFormDeleteLink($artistFormLi) {
      var $removeFormA = $('&lt;a href="#"&gt;diesen Künstler löschen&lt;/a&gt;');
      $artistFormLi.append($removeFormA);
  
      $removeFormA.on('click', function(e) {
          // prevent the link from creating a "#" on the URL
          e.preventDefault();
  
          // remove the li for the tag form
          $artistFormLi.remove();
      });
  }
  </code></pre>