1

I have been looking around for a clean solution on how to update (keep in sync) a many to many relationship?

I have the following scenario:

A Sprint Entity owns the Many To Many relationship towards the Ticket entity.

When editing a Ticket (or Sprint, but I am not there yet), I want to be able to select (checkboxes) the Sprints that this ticket belongs to. Upon persistance (save), I want to update my join table tickets_sprint (which is just a join table on ticket_id, sprint_id).

Adding Sprints to the Ticket seems easy enough, but removing Sprints from the Ticket is not reflected at all.

Code

Ticket Entity contains this method for adding a Ticket to a Sprint:

  public function setSprints($sprints) {
  /**
   * @var $sprint \AppBundle\Entity\Sprint
   */
  foreach ($sprints as $sprint) {
    $this->sprints[] = $sprint;
    $sprint->addTicket($this);
  }
}

I have read here that the only way to go would be to remove all relations and re-save them upon persistance.

Coming from the Laravel world, this hardly feels like a good idea :) This is how it is done in Laravel:

  /**
   * @param \App\User $user
   * @param \App\Http\Requests\StoreUserRequest $request
   * @return \Illuminate\Http\RedirectResponse
   * Update the specified resource in storage.
   */
   public function update(User $user, StoreUserRequest $request)
   {
    $user->fill($request->input());
    $user->employee_code = strtolower($user->employee_code);
    $user->roles()->sync($request->role ? : []);
    $user->save();
    \Session::flash('flash_message_success', 'The user was successfully updated.');
    return redirect()->route('frontend::users.show', [$user]);
  }

All suggestions are welcome!

Guardian
  • 369
  • 1
  • 5
  • 18
  • Possible duplicate of [Deleting record in many-to-many table](https://stackoverflow.com/questions/9653493/deleting-record-in-many-to-many-table) – svgrafov Nov 08 '17 at 09:03
  • @svgrafov, yes i was that one also. This also assumes that you check each relation individually. This is what i want to avoid. I would like to just "sync" the relations upon edit persistance as I am used to in Laravel. Thanks again though – Guardian Nov 08 '17 at 09:06
  • @svgrafov, this is an example from how it works in Laravel: https://pastebin.com/2jXcQ2EJ (focus on the $user->roles part) – Guardian Nov 08 '17 at 09:24
  • Question updated – Guardian Nov 08 '17 at 09:27

1 Answers1

1

The EntityType that you may use to create a multiple selectbox doesn't have a by_reference option like CollectionType.

If your Ticket Entity use the "inversedBy" side, you don't need to add the reference in the other object. So you can symply do this :

public function setSprints($sprints) {
  $this->sprints = $sprints;
}

Maybe this will be enough to add and remove your elements automatically (Sorry didn't try).

Otherwise you have to do it manually and you can create a new method to remove elements returns by the difference between your new ArrayCollection and the old one.

Fabien Salles
  • 1,101
  • 15
  • 24
  • Thanks Fabien. In my case the Sprint entity contains the inversedBy. That is where I have the code you mention in setTickets($tickets). So far, it seems that I will have to compute the difference or remove all associations and re-save them. – Guardian Nov 08 '17 at 10:22
  • 1
    Personnally, I don't like to couple my forms to my entities. I prefer to use additional objects like DTOs. If you want to understand why [this article](https://stovepipe.systems/post/rethinking-form-development) is very nice ! And in this way, it's ok to do it manually ! – Fabien Salles Nov 08 '17 at 10:30