Symfony2:使用 Sonata 文件字段上传 CSV 文件并将其内容存储在 Doctrine json_array 类型中

Symfony2: Using Sonata file field to upload a CSV file and store its content in a Doctrine json_array type

在 Symfony 项目中,我需要在实体上存储一些 table 数据,这些数据应该作为 CSV 文档上传到 Sonata admin 中。我的第一个想法是使用 Doctrine2 json_array 数据类型来存储数据,但我惊讶地发现这并不是一件容易的事。

经过一些研究,我发现 Symfony\Component\Form\DataTransformerInterface 似乎是将 CSV 文件转换为数组的正确选择。问题是 transform($value) 方法没有在 $value 参数中接收上传的文件,所以我坚持这个。

在实体管理员中 class 我有:

$formMapper
    [...]
    ->add($formMapper->create('discounts', 'file', array(
        'required' => false,
        'data_class' => null
      ))
      ->addViewTransformer(new CSVToArrayTransformer()))

其中 CSVToArrayTransformer 看起来像这样:

class CSVToArrayTransformer implements DataTransformerInterface
{
   public function transform($csvFile){
       // here should take place the csv to array transformation, but $csvFile is null
   }
}

有没有更好的获取方法?

Sonata documentation (Uploading and serving documents)所述,您应该在提交相应的表单后使用prePersistpreUpdate钩子来处理上传的文件。

使用这样的东西:

// Admin class

//...

protected function configureFormFields(FormMapper $formMapper)
    $formMapper
        //...
        ->add('file', 'file', array(
            'required' => false,
            'data_class' => null,
        ))
        //...
    ;
}

// Called on submit create form.
public function prePersist($entity)
{
    $this->manageFileUpload($entity);

    return $entity;
}

// Called on submit edit form.
public function preUpdate($entity)
{
    $this->manageFileUpload($entity);

    return $entity;
}

protected function manageFileUpload($entity)
{
    $entity->convertUploadedCsvToArray($entity->getFile())        
}

//...

在您的实体中:

// Entity

//...

// Unmapped property used for file upload
protected $file;

/**
 * Sets file.
 *
 * @param UploadedFile $file
 */
public function setFile(UploadedFile $file = null)
{
    $this->file = $file;
}

/**
 * Get file.
 *
 * @return UploadedFile
 */
public function getFile()
{
    return $this->file;
}

/**
 * Upload attachment file
 */
public function convertUploadedCsvToArray()
{
    if (null === $this->getFile()) {
        return;
    }

    $this->getFile()->move('youruploadpath', $this->getFile()->getClientOriginalName());

    // Do your logic with the csv file here
    $transformer = new CsvDataTransformer();
    $discounts = $transformer->transform($this->getFile());

    // Set the field using result of parsing.
    $this->setDiscounts($discounts);

    // Empty the 
    $this->setFile(null);
}

//...

希望这对您有所帮助。