Laravel 多列上的多对多同步()

Posted

技术标签:

【中文标题】Laravel 多列上的多对多同步()【英文标题】:Laravel Many-To-Many sync() on multiple columns 【发布时间】:2021-12-21 05:26:33 【问题描述】:

我正在尝试执行以下操作:

我有 Targets 模型; 我有字段模型; 这两个是通过数据透视表的多对多关系; 我希望能够使用多列唯一或主列,并使用 sync() 更新数据透视表上的“金额”列。

查看图片。

目标表:

字段表:

数据透视表(理想情况下):

正如您在数据透视表上看到的那样,有“年”和“月”,我只需要能够“同步”或更新特定字段的特定年/月的金额。

当我使用 sync() 执行此操作时(不要介意“UserTarget::”。为了简化,假设它是“Target::”):

它使用最后一个数组项更新数据透视表,我得到了这个:

但它必须是这样的:

我的目标模型:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\TargetField;

class Target extends Model

    use HasFactory;

    protected $table = 'targets';

    public function fields()
    
        // return $this->belongsToMany(
        //     RelatedModel, 
        //     pivot_table_name, 
        //     foreign_key_of_current_model_in_pivot_table, 
        //     foreign_key_of_other_model_in_pivot_table
        // );

        return $this->belongsToMany(
                'App\Models\Field',
                'target_field',
                'user_target_id',
                'user_target_field_id'
            )->withPivot(['year', 'month', 'amount', 'user_id']);
    


字段模型:

<?php

命名空间 App\Models;

使用 Illuminate\Database\Eloquent\Factories\HasFactory; 使用 Illuminate\Database\Eloquent\Model;

类字段扩展模型 使用 HasFactory;

protected $table = 'fields';

public function targets()

    // return $this->belongsToMany(
    //     RelatedModel, 
    //     pivot_table_name, 
    //     foreign_key_of_current_model_in_pivot_table, 
    //     foreign_key_of_other_model_in_pivot_table
    // );

    return $this->belongsToMany(
            'App\Models\Target',
            'target_field',
            'user_target_field_id',
            'user_target_id'
        )->withPivot(['year', 'month', 'amount', 'user_id']);

我在枢轴模型中这样做:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class TargetField extends Model

    use HasFactory;

    // pivot table to get user target fields (many to many)
    protected $table = 'target_field';

    public $incrementing = false;

    protected $primaryKey = ['user_target_id','user_target_field_id','user_id','year','month'];

    protected $fillable = ['user_target_id','user_target_field_id','user_id','year','month'];

    /**
     * Set the keys for a save update query.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    protected function setKeysForSaveQuery($query)
    
        $keys = $this->getKeyName();
        if(!is_array($keys))
            return parent::setKeysForSaveQuery($query);
        

        foreach($keys as $keyName)
            $query->where($keyName, '=', $this->getKeyForSaveQuery($keyName));
        

        return $query;
    

    /**
     * Get the primary key value for a save query.
     *
     * @param mixed $keyName
     * @return mixed
     */
    protected function getKeyForSaveQuery($keyName = null)
    
        if(is_null($keyName))
            $keyName = $this->getKeyName();
        

        if (isset($this->original[$keyName])) 
            return $this->original[$keyName];
        

        return $this->getAttribute($keyName);
    


您对我可能做错的事情有任何想法或建议吗?

所以基本上我希望能够保存/更新数据透视表上的多行(年、月、user_id),这些行的值与“金额”列不同。

救命!

【问题讨论】:

【参考方案1】:

您可以使用newPivotQuery 为数据透视表创建一个新的查询生成器。

$userTaraget=UserTarget::find(1);
// first delete old rows:
$userTaraget->Fields()->newPivotQuery()->where('user_id',188)->delete();
// then: insert new ones:
$userTaraget->Fields()->newPivotQuery()->saveMany([['year'=>2021, 'month'=>3, 'amount'=>5, 'user_id'=>188],
['year'=>2020, ....]);

【讨论】:

以上是关于Laravel 多列上的多对多同步()的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 同一模型上的多对多

Laravel 4:具有额外关系的多对多

Laravel 与渴望的多对多关系

Laravel 迁移中的多对多

Laravel 5 雄辩的多对多关系问题

从laravel中的多对多关系中获取单列