Laravel,sync()-如何同步数组并传递其他数据透视字段?


77

Laravel官方文档具有以下sync()功能:

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

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

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

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

提前致谢。


下面的答案并没有让我安静..您能提出您的解决方案吗?谢谢!
艾维斯(Evis)

很好的问题...所有教程都包含基本知识。
Shahid Karimi

Answers:


31

这对我有用

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

2
推荐这个版本是因为它很漂亮而且很干净,我怀疑对于任何后来的开发人员来说,理解和修改它都非常容易。
DevBodin

您可以更换->sync($photo_id_array, false)->syncWithoutDetaching($photo_id_array)为好。由于这是最优雅的解决方案,因此也要提出建议。
穆萨

141

为了sync与自定义数据透视表一起使用多个模型,您需要:

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

就是

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

编辑

回答评论:

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

1
亚雷克但如果我有,例如$speakers = \Input::get( 'speakers' )(其中$音箱成为一个数组),然后想通过$speakers沿=>array( 'is_speaker' => true)
ТомицаКораћ

1
如果没有的话。您创建如上所示的同步数组。使用ids键作为构建数组,或在HTML表单中以这种方式进行构建。
Jarek Tkaczyk 2014年

Jarek,我的\ Input :: get('speakers')返回ID数组。会是这样的工作:$training->users()->sync( array( $speakers => array( 'is_speaker' => true ) ) )
ТомицаКораћ

1
@JarekTkaczyk谢谢!评论的答案正是我想要的!
Pathros

1
@JarekTkaczyk看起来不错,但是每个项目都是通过单独的查询更新\插入的,这有点令人失望,因为它将影响性能。
tylik '18

4

装卸

Eloquent还提供了一些其他的辅助方法,以使使用相关模型更加方便。例如,假设一个用户可以有许多角色,而一个角色可以有许多用户。要通过在连接模型的中间表中插入一条记录来将角色附加给用户,请使用attach方法:

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

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

将关系附加到模型时,您还可以传递要插入到中间表中的其他数据数组:

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

如果要删除旧角色,而仅保留现在要附加的新角色,则也可以使用“同步”

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

可以通过传递“ false”作为第二个参数来更改默认行为。这将附加ID为1,2,3的角色,而不会影响现有角色。

在此模式下,同步的行为类似于attach方法。

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

参考:https : //laravel.com/docs/5.4/eloquent-relationships


1

将以下特征添加到项目中,并将其作为特征附加到模型类中。这很有用,因为这增加了使用多个枢轴的功能。可能有人可以清理一下并加以改善;)

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

模型:

namespace App;

use Illuminate\Database\Eloquent\Model;

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

用法:

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

1
我喜欢您的想法-最好将其转换为可重用的对象,而不是在下次出现此问题时复制它-尽管我建议您将其作为一个辅助函数,以便可以在任何地方和任何模型中使用。
DevBodin

0

只需您的字段及其附加到元素即可:

$user->roles()->sync([
   1 => ['F1' => 'F1 Updated']
]);

0
$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);

8
回答旧帖子时,如果您可以为答案提供一些上下文而不只是代码,那将很有帮助,因为它可能使它对其他人更有用。
David Buck

参见大卫·巴克斯的评论。另外,包括软件和/或系统和/或库版本;防止降低答案或删除答案的唯一方法。
ZF007
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.