1

I am pulling diseases from DB and presenting them in front-end with checkboxes:

<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
    @foreach($diseases as $disease)
        <div class="col-md-6">
            <div class="form-group">
                <label>{{ Form::checkbox('diseases','0','',
                                ['class' => 'grey','data-id'=> $disease->id]) }}
                    {{$disease->title}}
                </label>
                <div class="clearfix"></div>
            </div>
        </div>
    @endforeach
</div>

Once I submit the form, I get the result of the $request->diseases like this:

1:"1"
2:"1"
3:"0"
4:"1"
5:"0"
6:"0"
...

where first number represents disease_id, and other one presents whether the checkbox is checked or not. Relationships to the pivot table are made within models correctly, and what I try to do in controller is:

if ($request->has('diseases')) {
    $patient->diseases()->sync($request->diseases);
}

but this fails with error:

Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key 
constraint fails (`db_name`.`disease_patient`, CONSTRAINT `disease_patient_patient_id_foreign` 
FOREIGN KEY (`patient_id`) REFERENCES `patients` (`id`) ON DELETE CASCADE) (SQL: insert into 
`disease_patient` (`disease_id`, `patient_id`) 
values (17, {"1":"0","2":"0","3":"1","4":"1","5":"1","6":"1","7":"1","8":"1","9":"0","10":"1","11":"0","12":"1","13":"0","14":"0","15":"0","16":"0","17":"0","18":"0","19":"0","20":"0","21":"0","22":"0","23":"0"})) 

Relationship inside Patient model:

protected $guarded = ['id'];

public function diseases()
{
    return $this->belongsToMany('App\Disease', 'disease_patient', 'disease_id', 'patient_id');
}

EDIT:

When I do:

$diseases = array_keys(array_filter(json_decode($request->diseases, true)));
return $diseases;

I get the list of ID's like so:

0:1
1:2
2:8
3:14
4:15
5:21

And error:

(SQL: insert into `disease_patient` (`disease_id`, `patient_id`) values (33, 1))

With disease_id incrementing on each request

Norgul
  • 4,613
  • 13
  • 61
  • 144

1 Answers1

1

The issue here is that the sync method is NOT supposed to be an associative array. You should be passing it a single array containing the disease ID's to attach. To do this, you will need to pre-process your array:

if ($request->has('diseases')) {
    $diseases = array_keys(array_filter($request->diseases)));
    $patient->diseases()->sync($diseases);
}

If $request->diseases returns a Laravel Collection, you may need to call toArray() or cast it to an array first.

Reference: The "Syncing Associations" section of https://laravel.com/docs/5.4/eloquent-relationships#inserting-and-updating-related-models

Jeremy Harris
  • 24,318
  • 13
  • 79
  • 133
  • Hmm strange, I did a `gettype()` on the request, and I got string? Probably JSON string then. I am trying with `json_decode()`... – Norgul May 01 '17 at 19:05
  • What if you `dd($request);`? – Jeremy Harris May 01 '17 at 19:09
  • It is a huuuge list. But if I make that line `$diseases = array_keys(array_filter(json_decode($request->diseases, true)));` I get again integrity violation but now it is being fed with 2 values (27, 1) for `disease_id` and `patient_id`. Second one is ok, first one increments with each request – Norgul May 01 '17 at 19:14
  • Why are you JSON decoding it? – Jeremy Harris May 01 '17 at 19:16
  • Because I can't use array methods on string, and `toArray()` doesn't pass as valid. But when I dump the result of that line, I get an array of checked ID's. Maybe something else is wrong? Updated question – Norgul May 01 '17 at 19:18
  • Try swapping disease_id and patient_id in your belongsToMany definition. It looks like it might be trying to use a disease ID where patient ID is. – Jeremy Harris May 01 '17 at 19:24
  • Yes! I deleted both the foreign key and local key from relationship in model. Thanks! – Norgul May 01 '17 at 19:27