mpociot / versionable

Laravel Model versioning made easy
MIT License
735 stars 97 forks source link

Pivot tables #14

Open Desdichado opened 8 years ago

Desdichado commented 8 years ago

Right now i cant find a way to handle pivot tables and relations. Is this something you are considering to add in a near future or can give an example on how to do?

Usually when i want to version control stuff in my projects i need a version to include a number of models. Would be nice to be able to specify what models that makes a version. And if any of them is changed we would save a new version for all of them.. including pivot tables.

As an example: If i create a model called "Education", where each row is connected to a number of "Subject" with the help of a pivot table, where each "Subject" have some "Teacher" connected to them connected through a pivot table.

Then i would love the possibility to define that a version would consist of the tables: [educations, education_subject, subjects, subject_teacher teachers]

So if any of this tables are changed, create a new version.

Or go by Models like this: [ 'Education' => ['subjects'], 'Subject' => ['teachers'] ] where subjects and teachers is relations in this example.

Any thoughts?

boonstoppel commented 7 years ago

+1

blomdahldaniel commented 6 years ago

Wouldn't it be a possible solution to inside the Version object append columns for relationships and add an array of IDs / pivot values...? So then to rollback we have the right array to sync() to our relationship?

So for instance for the model Education we add the subject column containing the array of IDs and their pivot data:

// Education model adds column in Version object
$pivotRelations = [
  "subjects" => [ 2, 12, 42],
]

Reverting version would then include looping through the $pivotRelations array and syncing the array to the relationship

foreach( $pivotRelations  as $relation => $items ) {
  $this->$relation->sync($items)
}

This would also need custom exceptions and handling for when an relation item has been deleted since the old version.

The next thing would be storing the relationships. This could also be done via adding attribute to the model that is an array of the relationships that should be versioned. And listening to pivot events is hard. But if the pivot actions uses touch which would trigger "updated_at" to change.that would cause a new version to be created and when versions are created the $pivotRelations could be stored.

readable diff

The hard thing about this would be making this history readable. that could maybe be solved by complex attributes where you not only just declare what relationships that should be versioned but also the relationships columns that should be used as readable items. So the version data appended could be something like this:

// Education model adds column in Version object
$pivotRelations = [
  "subjects" => [  
    "sync" => [2, 12, 42],
    "readable" => ["Math", "Biology", "Yoga"]
]

The readable array can then act as the source of readable change..

Setting the value in the Education Model:

class Education extends Model {
  //...
  protected $pivotRelationships = [
    "subjects" => [ "keyField" => "id", "readableField" => "title"]
  ]
}

Am I getting somewhere or is this just a result of a late night no sleep brain..?