Laravel中批量更新关系的最佳做法

时间:2019-02-05 09:37:45

标签: php laravel relationship

批量更新关系的最佳做法是什么?

例如,我有一个Post模型,它具有以下关系:Lists(很多对很多),Tags(很多对多变种),Author(一个一)。编辑Post时,我想附加几个Lists,几个Tags并设置author_id

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

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

  1. 艰难的方式:
$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 个答案:

答案 0 :(得分:0)

我认为您在1)中描述的内容很好。如果变得更加复杂,则可以看看events,特别是在这种情况下,observers,您可以立即获得诸如创建,更新等事件。使用观察者,您可以执行以下操作:

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