1 year ago

Method to sync manyToMany relationship from model with custom pivot columns

Posted 1 year ago by DavidPetrov

I'm building a massive layer to copy a lot of models with a lot of such relationships so I really need this optimization. A basic example: I've got a model Scheme with the following relationship:

    public function imposts()
        //notice the custom attributes on the pivot
        return $this->belongsToMany('App\Impost')->withTimestamps()->withPivot('count');

I want to copy that scheme. Since it can't be achieved automatically with relationship cloning as well, I'm writing a method to do it in the same class:

    public function copy()
        $copy = $this->replicate(); //replicated the model with it's columns and a new id, quite useful

        //here I want to sync the copy's imposts with the original scheme's imposts BUT with the custom fields listed in the relationship definition. Is it possible? Something like:
        //$copy->imposts()->sync($this->imposts()->toSyncableArray()); //I'd imagine such a method, would be quite useful
    //a lot of relationships to clone here... incoming

        return $copy;

What I want that method to do is simply the following that I'm managing to achieve using this mapping:

$syncableImpostsArray = $scheme->imposts->mapWithKeys(function($imp){
    return [$imp->id => ['count' => $imp->pivot->count]];

This produces exactly the array I need for the sync method on a scheme with 5 imposts with respective counts:

  1 =>  [ "count" => 0 ]
  2 =>  [ "count" => 0 ]
  3 =>  [ "count" => 4 ]
  4 =>  [ "count" => 0 ]
  5 =>  [ "count" => 4 ]

As mentioned above, I need this for a lot of models with quite a lot of attributes (refactoring a project with copying functionality). Any ideas as to how to achieve this in a slightly more automatic way?

Thanks in advance for all suggestions!

Edit: Even if there isn't a method to automatically convert that to an array, a way to just get a list of customly added attributes to the relationship definition method would be sufficient as I can use the same function as above. I just need a way to retrieve an array like ['count', 'other_attribute', 'another_customly_set_attribute_to_pivot'] etc. Thanks again!

Please sign in or create an account to participate in this conversation.