Сопоставление столбца .csv с базой данных с помощью Symfony

Я хочу импортировать файл .csv с такими заголовками, как имя, адрес электронной почты и т. д. Как часть функции слияния почты в нашем веб-приложении (мы используем Symfony 3.4). До сих пор мне удалось сохранить файл .csv в базе данных с помощью Doctrine, когда я знаю, какими будут заголовки в .csv. Мне также нужно предоставить пользователю возможность изменять заголовок столбцов в случае, если заголовки отличаются или автоматическое сопоставление при импорте не работает.

Является ли здесь лучшим вариантом сохранить информацию в базе данных, а затем переместить данные с помощью Doctrine, или есть какой-то способ дать пользователю возможность сопоставить столбцы перед сохранением? Я относительно новичок как в Symfony, так и в Doctrine, поэтому не вижу решения.

Вот код контроллера:

public function usersListUploadAction(Request $request) {

    //  grab uploaded .csv file
    $file = $_FILES["file"]["tmp_name"];
    $fileimplode = implode("/", $file);

    // convert .csv if made on mac
    if (!ini_get("auto_detect_line_endings")) {
        ini_set("auto_detect_line_endings", '1');
    }
    //  create associative array from .csv
    $reader = Reader::createFromPath($fileimplode);

    $addedUsers = $reader->fetchAssoc();
    $em = $this->getDoctrine()->getManager();

    foreach($addedUsers as $row) {
        // check for existing users

        $emailAddress = $row["Email Address"];
        $user = $this->get('manager_user.repository')->findByEmailAddressWithoutParents($emailAddress);

        if ($user === []) {
            //  create new user
            $userTypeId = 1;
            $role = $request->get('roles', []);
            $firstname = $row["First Name"];
            $surname = $row["Last Name"];
            $email = $row["Email Address"];
            $username = (strtolower($row["First Name"].".".$row["Last Name"]));
            $phone = null;

            $userBuilder = $this->get('manager_user.manager')->newUser(        
                $userTypeId,
                $username,
                $phone,
                $email,
                $role,
                $password = null,
                $organisation = null,
                $emailResetPasswordLink = 0,
                $firstname,
                $surname,
                $name = null,
                $roles = []
            );



            $user = $userBuilder;

            // add email to contact_methods
            $cmType = $this->get('manager_user_contact_method_type.repository')->find(ContactMethodTypeInterface::EMAIL);
            $cmEmail = $this->get('manager_user_contact_method.builder')->createNew($cmType, $row["Email Address"], $user, 1);

            $em->persist($userBuilder);
            $em->persist($cmEmail);
        }       

            $em->flush();         
    }

    // return to user list page with list updated from .csv users

    $listId = $request->get('listId');
    $list = $this->get('manager.email.list_repository')->find($listId);
    $status = 1;
    //loop over the added users
    foreach($addedUsers as $row) {
        $userNameLower = (strtolower($row["First Name"].".".$row["Last Name"]));
        $userId = strval($this->get('manager_user.repository')->getUserIdByUserName($userNameLower));


        $user = $this->get('manager_user.repository')->find($userId);

        if (!$user->isInList($list)) { //this user is not in the list already so add it
            $dateSubscribed = new \DateTime();
            $emailCampaignListUser = new EmailCampaignListUser($user, $list, $dateSubscribed, $status);

            $em->persist($emailCampaignListUser);
        }
    }

    $em->flush();


   return $this->redirectToRoute('manager_email_campaign_lists_users_upload_check', array('listId' => 1));  
}

Функция сопоставления - хорошая идея, но подразумевает, что перед импортом нужно сделать еще один шаг. Вы можете легко сделать это, указав ожидаемые поля и распечатав заголовки csv.

Alexandre Painchaud 30.07.2018 13:40

Привет, Александр, не могли бы вы подробнее рассказать, как этого добиться?

h1mupstairs 30.07.2018 14:10
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
2
769
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Приведу пример (не полный). Как я уже говорил, вы можете так поступать.

  1. Первый шаг, пользователь может сопоставить поля ожидал с полями заголовок csv
  2. Импортируйте данные, используя ранее созданное сопоставление.

Для первый шаг вы можете выбрать желаемое решение для внешнего интерфейса, например Drag & Drop.

На мой взгляд, вы должны определить свои ключи

 //this is your code
 //Here we define that "firstname" is your key for the first name
 $fields = ["firstname","lastname"];

Вторая часть первого шага - получение заголовка CSV с использованием fgetcsv в первой строке (строке заголовка).

    if (($handle = fopen("yourcsv.csv", "r")) !== FALSE) {
       //Here you get all csv headers
       $header = fgetcsv($handle, 1000, ","); 
       fclose($handle);
    }

На этом этапе после того, как вы (или пользователь) выполнили сопоставление, вы можете сохранить сопоставление в базе данных, если это действительно необходимо, или просто использовать POST для получения сопоставления на втором этапе.

Второй шаг мы анализируем файл csv, пропуская первую строку, и используем ранее выполненное сопоставление для правильного получения данных.

 //Your mapping is stored in $mapping by example
  //it contains "fieldname" => "csv index" example "firstname" => 3
  if (($handle = fopen("test.csv", "r")) !== FALSE) {
  //skip header line here
  fgetcsv($handle, 1000, ",");
  while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        //$data contain each user data
        $userBuilder = $this->get('manager_user.manager')->newUser(        
           $data[$mapping['firstname']],
           $data[$mapping['lastname']],
           //etc...
         );
    }
  fclose($handle);
}

Надеюсь, это поможет и прояснится.

Другие вопросы по теме