2
\$\begingroup\$

I've been developing an application based on Symfony 3, and part of that application involves an import process where a user can upload csv files. One thing that I've never been too sure about with symfony is using the forms component without a database entity to attach it too. In the past I've typically just used an array to hold the form data, but this always felt improper. This time I decided to try building an entity class to base the form on, even though it has no mapping to anything in the database.

This is the entity I created. In addition to defining the fields for the form I also setup validation to ensure at least one of the fields has been populated.

class StudentImportFiles {
    /** @var File */
    private $studentList;
    /** @var File */
    private $transferList;
    /** @var File */
    private $enrollmentList;

    public static function loadValidatorMetadata(ClassMetadata $metadata){
        $metadata->addConstraint(new Callback(function(self $self, ExecutionContextInterface $context){
            if (!($self->studentList || $self->transferList || $self->enrollmentList)){
                $context->addViolation('At least one import file must be selected');
            }
        }));
    }

    public function getStudentList(){
        return $this->studentList;
    }

    public function setStudentList($studentList){
        $this->studentList = $studentList;

        return $this;
    }

    public function getTransferList(){
        return $this->transferList;
    }

    public function setTransferList($transferList){
        $this->transferList = $transferList;

        return $this;
    }

    public function getEnrollmentList(){
        return $this->enrollmentList;
    }

    public function setEnrollmentList($enrollmentList){
        $this->enrollmentList = $enrollmentList;

        return $this;
    }
}

This is the form type I created. It simply maps to the above entity and ensures it is valid.

class StudentImportFilesType extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options){
        $builder
            ->add('studentList', FileType::class, [
                'required' => false
            ])
            ->add('transferList', FileType::class, [
                'required' => false
            ])
            ->add('enrollmentList', FileType::class, [
                'required' => false
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver){
        $resolver->setDefaults([
            'data_class' => StudentImportFiles::class
            , 'constraints' => [
                new Valid()
            ]
        ]);
    }
}

Is this proper usage of the forms component for such a scenario? Are there any improvements that could be made?

\$\endgroup\$
1
  • \$\begingroup\$ Your idea is right, but I'd just use DTO instead of Entity. Pass DTO into form and the Request POSTed data will be in a nice object with getters etc. And yes, arrays should only be used when A) Unavoidable; B) The same class;. Passing arrays through different app layers and classes is the root cause of evil (aka bugs) \$\endgroup\$
    – James
    Nov 9, 2022 at 15:44

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.