Laravel,sync()-如何同步一个数组并传递额外的枢轴字段?

正式的 Laravel 文档有这个关于 sync()的功能:

$user->roles()->sync( array( 1, 2, 3 ) );

您还可以将其他数据透视表值与给定的 ID 关联起来:

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

在后一个示例中,只添加一个枢轴行。我不明白的是,如果有多个行要同步,我如何关联其他枢轴表记录?

先谢谢你。

157423 次浏览

In order to sync multiple models along with custom pivot data, you need this:

$user->roles()->sync([
1 => ['expires' => true],
2 => ['expires' => false],
...
]);

Ie.

sync([
related_id => ['pivot_field' => value],
...
]);

edit

Answering the comment:

$speakers  = (array) Input::get('speakers'); // related ids
$pivotData = array_fill(0, count($speakers), ['is_speaker' => true]);
$syncData  = array_combine($speakers, $pivotData);


$user->roles()->sync($syncData);

This works for me

foreach ($photos_array as $photo) {


//collect all inserted record IDs
$photo_id_array[$photo->id] = ['type' => 'Offence'];


}


//Insert into offence_photo table
$offence->photos()->sync($photo_id_array, false);//dont delete old entries = false

Attaching / Detaching

Eloquent also provides a few additional helper methods to make working with related models more convenient. For example, let's imagine a user can have many roles and a role can have many users. To attach a role to a user by inserting a record in the intermediate table that joins the models, use the attach method:

$user = App\User::find(1);


$user->roles()->attach($roleId);

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]);

You can also use Sync if you want to remove old roles and only keep the new ones you are attaching now

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

The default behaviour can be changed by passing a 'false' as a second argument. This will attach the roles with ids 1,2,3 without affecting the existing roles.

In this mode sync behaves similar to the attach method.

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

Reference: https://laravel.com/docs/5.4/eloquent-relationships

Add following trait to your project and append it to your model class as a trait. This is helpful, because this adds functionality to use multiple pivots. Probably someone can clean this up a little and improve on it ;)

namespace App\Traits;


trait AppTraits
{
/**
* Create pivot array from given values
*
* @param array $entities
* @param array $pivots
* @return array combined $pivots
*/
public function combinePivot($entities, $pivots = [])
{
// Set array
$pivotArray = [];
// Loop through all pivot attributes
foreach ($pivots as $pivot => $value) {
// Combine them to pivot array
$pivotArray += [$pivot => $value];
}
// Get the total of arrays we need to fill
$total = count($entities);
// Make filler array
$filler = array_fill(0, $total, $pivotArray);
// Combine and return filler pivot array with data
return array_combine($entities, $filler);
}
}

Model:

namespace App;


use Illuminate\Database\Eloquent\Model;


class Example extends Model
{
use Traits\AppTraits;
// ...
}

Usage:

// Get id's
$entities = [1, 2, 3];
// Create pivots
$pivots = [
'price' => 634,
'name'  => 'Example name',
];
// Combine the ids and pivots
$combination = $model->combinePivot($entities, $pivots);
// Sync the combination with the related model / pivot
$model->relation()->sync($combination);

Simply just append your fields and their values to the elements:

$user->roles()->sync([
1 => ['F1' => 'F1 Updated']
]);
$data = array();
foreach ($request->planes as $plan) {
$data_plan = array($plan => array('dia' => $request->dia[$plan] ) );
array_push($data,$data_plan);
}
$user->planes()->sync($data);

Putting this here in case I forget it later and Google it again.

In my case I wanted the extra column to have the same data for each row

Where $syncData is an array of IDs:

$syncData = array_map(fn($locationSysid) => ['other_column' => 'foo'], array_flip($syncData));

or without arrow

$syncData = array_map(function($locationSysid) {
return ['ENTITY' => 'dbo.Cli_Core'];
}, array_flip($syncData));

(array_flip means we're using the IDs as the index for the array)

There is now a ->syncWithPivotValues($ids, $pivotValues) method available if you want to set the same pivot value for all synced items.

Example from the doc:

$user->roles()->syncWithPivotValues([1, 2, 3], ['active' => true]);
    foreach ($request->exercise_id as $key => $exercise_id) {
$data_plan[$exercise_id] = [
'serie' => $request->serie[$key],
'observation' => $request->observation[$key],
];
}