phplaravelmany-to-many

Laravel use sync on a many to many that includes a multiple extra fields


I'm trying to use sync on a many to many that includes a status and a comment. I can sync the applications without status and comment just fine.

NewUserAccount Model

public function applications()
{
   return $this->belongsToMany('App\Application', 'new_user_account_applications', 'new_user_id')->withPivot('application_comment', 'status');
}

Application Model

public function newUserAccounts()
{
  return $this->belongsToMany('App\NewUserAccount', 'new_user_accounts_applications', 'new_user_id')->withPivot('application_comment', 'status');
}

My NewUserAccountController

public function store(StoreRequest $request)
    {
       $userAccount = NewUserAccount::create(array_merge(
            $request->all(),
            ['submitted_by' => $requester->id],
            ['start_date' => Carbon::parse($request->input('start_date'))],
            ['account_expires' => $request->accountExpires('newAccountExpireDate')],
            ['company_id' => $requester->company_id],
            ['username' => $request->manuallyAssignId()]
        ));

       // Here I sync applications and include application comment and status 
       $userAccount->applications()->sync($request->applications, ['application_comment' => $request->application_comment, 'status' => 0]);

       ....

    }

My pivot showing status and comment correctly
enter image description here

My form. Here is where I'm not sure how to handle the comment and get it to save with each application pivot record.

@foreach($applications as $application)
    <label class="k-checkbox">
        <input value="{{ $application->id }}" name="applications[]" type="checkbox">{{ $application->application_name }} <span></span> 
    </label>

    <div class="form-group col-lg-4 mb-3">
        <label>Comments</label>
            <textarea name="application_comment[]" class="form-control" rows="2"></textarea>
    </div>
@endforeach

Solution

  • First, you need to set the correct index for the application_comment attribute in your textarea. It's needed to correctly determine the comment for each application.

    @foreach($applications as $application)
        ...
        <textarea name="application_comment[{{ $application->id }}]" class="form-control" rows="2"></textarea>
        ...
    @endforeach
    

    Then, you just need to format your data to:

    $userAccount->applications()->sync([
        application_id_1 => ['application_comment' => 'comment for application_id 1'],
        application_id_2 => ['application_comment' => 'comment for application_id 2'],
        ...
    ]);
    

    So, here it is

    $applications = collect($request->applications)->mapWithKeys(function ($appId) use ($request) {
        return [$appId => [
            'application_comment' => $request->input('application_comment')[$appId],
            'status' => 0,
        ]];
    });
    
    $userAccount->applications()->sync($applications);