Лучшая практика массового обновления отношений в Laravel - PullRequest
0 голосов
/ 05 февраля 2019

Какова наилучшая практика массовых обновлений отношений?

Например, у меня есть 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. ИМХО, не хорошо.Может быть, я ошибаюсь.

Трудный путь:
$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 голосов
/ 05 февраля 2019

Я думаю, что вы описали в 1) в порядке.Если это станет более сложным, возможно, посмотрите на события и, в частности, в этом случае наблюдатели , где вы получите такие события, как созданные, обновленные, ... из коробки.С наблюдателями вы могли бы сделать что-то вроде этого:

class PostObserver
{
    public function updated(User $user)
    {
        // Make appropriate updates on lists and tags here
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...