Laravel - обновить базу данных, чтобы она соответствовала массиву - PullRequest
0 голосов
/ 19 марта 2019

У меня есть таблица «категории» с полями: id, parent_id, name, order. Parent_id - это внешний ключ для идентификатора другой категории. Теперь мой контроллер получает массив из запроса AJAX:

public function saveCategories(Request $request) {
    if(!$request->ajax()) return Response::json(['error' => 'Received data has invalid format'], 500);

    $data = $request->all()['data'];
    return $data;
}

Полученный массив имеет те же поля, что и таблица, поэтому: id, parent_id, имя и порядок.

Какой самый удобный способ обновить таблицу «категории» с данным массивом? Что нужно иметь в виду:

  1. Элементы с таким же идентификатором, что и в массиве, только что обновились.

  2. Добавляются новые элементы, так что те, которые 'id' еще не найдены в базе данных, должны быть добавлены.

  3. Элементы, которые не найдены, но встречаются в базе данных, должны быть удалены.

Нужно ли проходить через все элементы и изменять базу данных вручную?

E: Некоторые из других таблиц относятся к категориям, поэтому решение удалить каждую строку и создать все записи с нуля не вариант.

E2: Вдохновленный ответом @EduardoJunior, мне удалось сделать следующее:

public function saveCategories(Request $request) {
  if(!$request->ajax()) return Response::json(['error' => 'Sent data invalid format'], 500);

  $data = $request->all()['data'];
  $all_ids = array_map(function($category){

  Category::updateOrCreate(['id' => $category['id']], ['name' => $category['name'],
    'parent_id' => $category['parent_id'], 'order' => $category['order']]);
  return $category['id'];

    }, $data);

  Category::whereNotIn('id', $all_ids)->delete();
  return ['success' => true];
}

Создает и изменяет строки, но только изменяет / добавляет поле имени. Parent_id остается неизменным или получает значение по умолчанию, равное нулю, в новых строках, также как и в поле заказа Если я удалил одну категорию, так что Category :: whereNotIn () должен быть запущен, сервер выдает ошибку 500.

E3: Конечно, это была проблема с $ fillable, я чувствую себя так глупо. Также удаление работает сейчас. Однако 'parent_id' => $ category ['parent_id'] в updateOrCreate () по-прежнему не работает. Имя и порядок и сохранены правильно, но это поле не.

Ответы [ 3 ]

0 голосов
/ 19 марта 2019

Еще один способ сделать это

 /// delete not in list
    Category::whereNotIn($data->pluck('id'))->delete();

    /// add or update array
    foreach($data as $row){ 
        Category::updateOrCreate(
            [$row['id']], /// id of model
            [$row] /// model array
        );
    }
0 голосов
/ 19 марта 2019

Благодаря @Eduardo Junior мне удалось решить проблему:

$data = $request->all()['data'];

$all_ids = array_map(function($category){

  Category::updateOrCreate(['id' => $category['id']], ['name' => $category['name'],
    'order' => $category['order']]);
  return $category['id'];

}, $data);
Category::whereNotIn('id', $all_ids)->delete();

foreach($data as $category) {
  $child = Category::find($category['id']);
  $child->parent()->associate(Category::find($category['parent_id']));
  $child->save();
}

Примечание: обновление parent_id выполняется с помощью метода Eloquent associate после создания всех новых категорий, чтобы избежать конфликтов.

0 голосов
/ 19 марта 2019

Вы можете сделать так:

    DB::beginTransaction();

    try {

        //Upsert all items, and store their ids to delete the ones that are not present.
        $all_ids = array_map(function($category){

            DB::statement(' INSERT INTO categories (id, parent_id, name, order)'.
                        ' VALUES ('.$category['id'].','.$category['parent_id'].','.$category['name'].','.$category['order'].')'.
                        ' ON DUPLICATE KEY UPDATE parent_id='.$category['id'].','.
                                                'name='.$category['name'].','.
                                                'order='.$category['order']);

            return $category['id'];

        }, $data = $request->all()['data']);

    } catch(\Exception $e) {
        DB::rollback();
        throw $e;
    }

    Category::whereNotIn('id', $all_ids)->delete();

    DB::commit();
  • Добавлена ​​обработка транзакций для повышения производительности и поддержания согласованности базы данных в случае возникновения какого-либо исключения.
  • Я не сделалне проверяю, но я думаю, что это может направить вас на правильный путь.:)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...