سؤال

Background

I'm creating a database revolving around food allergies and I have a many to many relationship between foods and allergies. There is also a pivot value called severity which has a numerical number representing the severity of the allergy for that food item.

This link table looks like this;

food_id|allergy_id|severity
-------|----------|--------
     1 |        1 |      3
     1 |        4 |      1
     2 |        2 |      1

The problem

When trying to update the link table with Eloquent (where $allergy_ids is an array)

$food->allergies()->attach($allergy_ids);

How would I go about adding multiple values to this pivot table at once along with the pivot values?

I can add all the allergy_id's for a particular food item in one go using the above line, but how can I also add in the severity column at the same time with an array of various severity values? Maybe something like

$food->allergies()->attach($allergy_ids, $severity_ids);

Edit: There could be between 0-20 allergies for a specific food item, and a severity rating from 0-4 for each allergy, if this helps at all.

هل كانت مفيدة؟

المحلول

You can.

From this example in Docs (4.2, 5.0):

$user->roles()->sync(array(1 => array('expires' => true)));

Hardcoded version for the first two rows:

$food = Food::find(1);
$food->allergies()->sync([1 => ['severity' => 3], 4 => ['severity' => 1]]);

Dynamically, with your arrays $allergy_ids and $severities in a compatible state (size and sort), you shall prepare your sync data before. Something like:

$sync_data = [];
for($i = 0; $i < count($allergy_ids); $i++))
    $sync_data[$allergy_ids[$i]] = ['severity' => $severities[$i]];

$food->allergies()->sync($sync_data);

نصائح أخرى

You can't do it like you' like so I suggest a simple loop:

foreach ($allergy_ids as $key => $id)
{
  $food->allergies()->attach($id, array_get($severity_ids, $key));
  // should you need a sensible default pass it as a 3rd parameter to the array_get()
}

workaround However if you wanted to attach multiple allergies with single severity level/id then you could do this:

$food->allergies()->attach($allergy_ids, array('severity' => $singleSeverityValue));

From version 5.1 of Laravel (Currently in Laravel 10.x) onwards it is possible to pass an array as a second argument with all the additional parameters that need to be saved in the intermediate table. As you can read in the documentation

When attaching a relationship to a model, you may also pass an array of additional data to be inserted into the intermediate table:

$user->roles()->attach($roleId, ['expires' => $expires]);

For convenience, attach and detach also accept arrays of IDs as input:

$user->roles()->attach([1 => ['expires' => $expires], 2, 3]);

Then you can simply do

$food->allergies()->attach([1 => ['severity' => 3], 4 => ['severity' => 1]]);

So, on Laravel 9, passing the ids in the array worked for me. Likeso,

$user->roles()->attach([$a->id,$b->id,$c->id]); and so on.

I guess instead of passing the string. We can pass just the id or else convert the string into array.

Easiest indeed is to attach with the extra data, like so:

$retailer->paymentmethods()->attach($paymentmethod, array('currency' => $paymentmethod->currency));

change out the values for food allergy severity, but you get the hint... :-)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top