【问题标题】:How to handle a bad CSV file import in Symfony/PHP如何在 Symfony/PHP 中处理错误的 CSV 文件导入
【发布时间】:2021-03-09 13:58:21
【问题描述】:

我正在毫无问题地从 csv 上传 大量数据,但 我想保护可能的用户错误,因为他们可能会放格式错误的 csv ...

问题是每次启动表单时我都会截断表格...


ImportController.php

       $form = $this->createFormBuilder()
       ->add('form', FileType::class, [
           'attr' => ['accept' => '.csv',
           'class' => 'custom-file-input'],
           'label' => 'Import'
       ])
       ->getForm();
       
       $form->handleRequest($request);

           if ($form->isSubmitted() && $form->isValid()) 
           {
               /** 
                * @var UploadedFile
                */
               $file = $form->get('form')->getData();  
               $connection = $em->getConnection();
               $platform = $connection->getDatabasePlatform();
               $connection->beginTransaction();
               $connection->executeQuery($platform->getTruncateTableSQL('MyTable', true));
               $this->getDoctrine()->getManager()->getRepository(MyTable::class)->importMyData($file);           
       
               $this->addFlash('success',"The csv has been successfully imported");
               return $this->redirectToRoute('import');
           } 


MyTableRepository.php

public function importMyData($file)
    {
        $em = $this->entityManager;

        if (($handle = fopen($file->getPathname(), "r")) !== false) 
        {
            $count = 0;
            $batchSize = 1000;
            $data = fgetcsv($handle, 0, ","); 

            while (($data = fgetcsv($handle, 0, ",")) !== false) 
            {
                $count++;
                $entity = new MyTable();

                // 40 entity fields...
                $entity->setFieldOne($data[0]);                
                $entity->setFieldTwo($data[1]); 
                //....
                $entity->setFieldForty($data[39]); 

                $em->persist($entity);

                if (($count % $batchSize) === 0 )
                {
                    $em->flush();
                    $em->clear();
                }
            }
            fclose($handle);
            $em->flush();
            $em->clear();
        }
    }

我只希望在启动错误的 CSV 文件时该表不会被截断

【问题讨论】:

  • 你知道如何检测坏文件吗?
  • 嗯,我猜不是,但问题不是文件本身,而是内容。
  • 好吧,当您开发一种确定文件坏了的方法时,检查就变成了一个微不足道的if 条件。
  • 但是我应该在什么级别检查这个?避免截断?在表格中?
  • 最自然的地方是表单提交代码。获取上传的文件,对其进行测试,然后如果它不正确则不要运行事务,并为用户返回带有错误的响应。

标签: php csv symfony truncate


【解决方案1】:

您可以在插入数据库之前清理和验证数据。你可以尝试很多方法。首先,我会使用 Symfony 文件验证器来确保检查是否已上传有效文件。

Symfony File Validator

要验证每一行,您可以使用自定义回调验证器或数组的原始值 Validate Raw Data

//call the validator in the repository
$validator = Validation::createValidator();

// sample input
$input = [
'field_1' => 'hello',
'field_2' => 'test@email.tld',
'field_40' => 3
];

//define the constraints for each row
$constraint = new Assert\Collection([
// the keys correspond to the keys in the input array
'field_1' => new Assert\Collection([
    'first_name' => new Assert\Length(['min' => 101]),
    'last_name' => new Assert\Length(['min' => 1]),
]),
'field_2' => new Assert\Email(),
'field_40' => new Assert\Length(['min' => 102])
]);

while (($data = fgetcsv($handle, 0, ",")) !== false) {
  $violations = $validator->validate($data, $constraint);
  
  // you can skip the row or log the error
  if ($violations->count() > 0) {
    continue;
  }
}

【讨论】:

    【解决方案2】:

    感谢大家,我很愚蠢,我只是放了一个“try catch”,如果 importMyData 函数中发生错误,它会返回其他内容,然后我检查我的控制器,如果这返回值......如果是这样,我会重定向等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-14
      • 2011-04-03
      • 1970-01-01
      • 2021-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多