Laravel импорт данных из Excel

112
25 декабря 2020, 18:30


Вопрос уже не раз задавался в сообществе, но меня интересует детали скорее, чем само решение. Итак, ситуация рядовая: есть таблицы

  • Users (ID, name)
  • Cards (ID, number)
  • User_cards (user_id, card_id)



Есть форма, в которой выбирается excel файл, в котором две колонки: ФИО, номер карты и таких записей, скажем, 10 000 в этом файле.

А теперь собственно вопрос: как лучше всего реализовать проверки:

  1. Пользователь с таким именем существует в таблице Users
  2. Карта с таким номером существует в таблице Cards

Я понимаю что это можно сделать через обычные Eloquent

// ищем пользователя по ФИО 
User::where('name', $userName)->first();
// ищем карту по номеру
Card::where('number', $cardNumber)->first();

Но. Если бы речь шла о чистом PHP, то я бы использовал Prepared Statement, для уменьшения нагрузки на сервер БД, а так получается очень много однотипных запросов без экономии.

Для парсинга самого excel я использую Laravel Excel. https://laravel-excel.com/ Такую работу я убираю в фон, в Jobs, в очереди, но как работать в Laravel с подготовленными выражениями я все таки не понимаю. В качестве СУБД использую MySQL 5.0.11

Answer 1
  1. Конвертируем XLS/XLSX в CSV и кладём в secure_file_priv
  2. Создаём временную таблицу (тип и размер данных корректируется в соответствии с данными)

    DROP TEMPORARY TABLE IF EXISTS temp;        
    CREATE TEMPORARY TABLE temp ( user VARCHAR(255),
                                  card VARCHAR(16) ) Engine = Memory;
    
  3. Загружаем данные из CSV

    LOAD DATA INFILE 'data.csv' INTO TABLE temp;
    
  4. Добавляем отсутствующих юзеров, игнорируем существующих (предполагается, что имеется уникальный индекс users(name))

    INSERT IGNORE INTO users (name)
    SELECT DISTINCT user
    FROM temp;
    
  5. Делаем то же с картами (предполагается, что имеется уникальный индекс cards(number))

    INSERT IGNORE INTO cards (number)
    SELECT DISTINCT card
    FROM temp;
    
  6. Пополняем таблицу соответствия

    INSERT IGNORE INTO user_cards (user_id, card_id)
    SELECT u.id, c.id
    FROM users u, temp t, cards c
    WHERE u.name = t.user
      AND c.number = t.card
    
  7. Если нужно - удаляем временную таблицу

    DROP TEMPORARY TABLE temp;
    

Все запросы можно собрать в одну хранимую процедуру - тогда из Laravel нужно будет только выполнить конвертацию и затем выполнить эту процедуру.

READ ALSO
Doctrine наследование Single Table

Doctrine наследование Single Table

Если использовать Single Table наследование в doctrineИ у 2 разных дочерних классов будут свойства с одинаковым именем к примеру (price), возникнут какие...

119
Autoload psr-4 with composer

Autoload psr-4 with composer

Прошу помощи, тк

101
Браузер скачивает файл *.php

Браузер скачивает файл *.php

Проблема такова: при обращении к web-сайту по ip, страница корректно открывается, но стоит обратиться по dns - mysitetest

108
Парсинг в массив из файла. php

Парсинг в массив из файла. php

Есть большой файл бекапа раунда (кс:го) и я пытаюсь его распарсить в массив для дальнейшего выводаЧто это за тип и как его "разобрать"

132