العمود المطابق. csv لقاعدة البيانات باستخدام Symfony

1

أريد استيراد ملف .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));  
}

1 إجابة

0

أقدم لكم مثالاً (غير ممتلئ). كما علقت يمكنك معالجة مثل هذا.

  1. الخطوة الأولى ، يمكن للمستخدم مطابقة الحقول المتوقعة مع حقول رأس ملف csv
  2. استيراد البيانات باستخدام التعيين الذي تم إجراؤه مسبقًا.

للخطوة الأولى ، يمكنك اختيار حل الواجهة الأمامية الذي تريده ، مثل السحب والإفلات.

في رأيي عليك تحديد مفاتيحك

 //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);
}

آمل أن يساعد هذا وواضحا.

:مؤلف
فوق
قائمة طعام