Laravel 中批量更新关系的最佳实践

Posted

技术标签:

【中文标题】Laravel 中批量更新关系的最佳实践【英文标题】:Best practice of mass update relations in Laravel 【发布时间】:2019-06-29 02:11:43 【问题描述】:

大规模更新关系的最佳实践是什么?

例如,我有 Post 模型,它具有这样的关系:Lists(多对多)、Tags(多对多变形)、Author(一对一)。当我编辑Post时,我想附加几个Lists,几个Tags并设置author_id

    简单的方法:
$post->fill($request->all);
$post->saveOrFail();
$post->lists()->sync($request->lists);
$post->tags()->sync($request->tags);

不错,但如果关系超过两个,例如 10。恕我直言,不好。也许我错了。

    艰难的路:
$post->fill($request->all);
$post->saveOrFail();
$post->massUpdateRelations($request->only(['lists', 'tags']));

function massUpdateRelations($data)

    $this->massFill($data);
    $this->massSave();


function massFill($data, $model = null)

    $uses = array_flip(class_uses_recursive(static::class));
    $relationModels = [];
    if (is_null($model)) 
        $model = $this;
    
    if (!$model->wasRecentlyCreated) 
        $relationModels[] = $model;
    
    foreach ($data as $name => $value) 
        if (is_array($value)) 
            $relationInfo = $model->$name();
            if ($relationInfo instanceof BelongsToMany) 
                $relationInfo->sync($value);
             elseif ($relationInfo instanceof HasMany) 
                $this->afterMassSave[] = function () use ($relationInfo, $value) 
                    $relationInfo->delete();
                    $relationInfo->createMany($value);
                ;
             elseif ($relationInfo instanceof HasOne) 
                $this->afterMassSave[] = function () use ($relationInfo, $value) 
                    $relationInfo->delete();
                    $relationInfo->create($value);
                ;
             else 
                $relation = $model->$name;
                $relationModels = array_merge($relationModels, $this->massFill($value, $relation));
            
         else 
            if ($model->isFillable($name)) 
                $model->setAttribute($name, $value);
            
        
    
    $this->relationModels = $relationModels;

    return $relationModels;


function massSave()

    foreach ($this->relationModels as $relationModel) 
        $relationModel->save();
    
    foreach ($this->afterMassSave as $item) 
        call_user_func($item);
    

也许对许多关系都有好处,但看起来很糟糕。并且在验证数据关系数组时遇到问题。

我正在尝试在我的问题中搜索答案,但没有效果。

【问题讨论】:

【参考方案1】:

我认为您在 1) 中描述的内容很好。如果它变得更复杂,也许看看events,特别是在这种情况下observers,您可以在其中获得诸如创建、更新、...等开箱即用的事件。对于观察者,您可以执行以下操作:

class PostObserver

    public function updated(User $user)
    
        // Make appropriate updates on lists and tags here
    

【讨论】:

以上是关于Laravel 中批量更新关系的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

updateOrCreate - Laravel 中的批量分配异常

oracle批量更新的问题

NHibernate中的批量更新

将数据批量插入 Oracle 数据库的最佳方法

在Salesforce中Upsert批量与批量Upsert

批量更新/删除EF5