jeudi 18 juin 2020

Laravel 5.8 - How to properly replicate() records and their polymorphic relationships?

Outline

We have an application that manages data inputs from separate sources. Users can enter the data in the main form, but it can also originate from another, which is saved in a separate table.
We keep track where the data came from by an optional polymorphic relationship. If the polymorphic relationship is set, we know to lock the input in the main form and let users know the data was entered from the other form.
Data is organized in collections in both places (think of them as columns in an Excel sheet):

The exact names are confidential, but this is a basic outline with names changed:

- tasks (id, title, task_parent_id)
  - collections (id, title)
    - data (id, value, datasourceable_type, datasourceable_id)
  - collectionPants
    - pantsData (id, value)

This does not call for a polymorphic relationship yet, true. But we will have collectionShirts later with shirtsData.
Here are the corresponding models to use in terms of the discussion:

<?php

  class Task {}

  class Collection {}

  class Data {}

  class CollectionPants {}

  class PantsData {
    public function collectionData()
    {
      return $this->morphMany('App\Models\Data', 'datasourceable');
    }
  }

So if datasourceable is set, we know data comes from pantsData within collectionPants.

Now replicate all of that

Then we want to be able to replicate() a task, all its collections and the data.

<?php

  class Task {
    // ...
    public function clone() {
      $task = $this->replicate();
      $task->task_parent_id = $this->id;
      $task->push();

      // ... see below
    }
    // ...
  }

We then proceed to replicate() the collections and their data. This works and is currently no issue.
But I was thinking (maybe overthinking?): When a PantsData model is replicated and the corresponding Data model is replaced as well, both their IDs are updated of course. But the polymorphic relationship will point to the old Data record if datasourceable_id is not updated as well.

So how do?

Replicating the Data model first means I have to update the datasourceable_id later when PantsData has been replicated. I cannot traverse the polymorphic relationship, because PantsData will have a new ID once it's replicated.
Replicating PantsData first means I cannot traverse the polymorphic relation back to Data, because Data's id is not replicated yet and will be different once I replicate it later.

I'm currently trying to think up an elegant solution to make this work.
Should I keep track of every PantsData replicated and update datasourceable_id to their new IDs afterwards?
Or does Laravel have a more elegant solution to automagically update the polymorphic relationship as well when replicating?
Can this be applied later for replicating the planned collectionShirts with their shirtsData as well without much implementation overhead?

Thanks in advance!



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire