user2559108
user2559108

Reputation:

Symfony3 form type, reference other entity by id

I am building an API and using forms for data binding, now i want to be able to pass the ID of an entity, get the reference and attach it to the item, here is an example:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('credit');
    $builder->add('currency', 'currency');
    $builder->add('borrower', BorrowerType::class, [
        'required' => true
    ]);

    $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
        $data = $event->getData();
        $borrower = $this->em->getReference(Borrower::class, $data['borrower']);
        $data['borrower'] = $borrower;
    });
}

This returns "ERROR: This value is not valid.\n"

Here is my test request:

    $client->request('POST', $endpoint, [
        'loan' => [
            'credit' => '1000',
            'currency' => 'EUR',
            'borrower' => $borrower->getId()
        ]
    ]);

Upvotes: 2

Views: 965

Answers (2)

DonCallisto
DonCallisto

Reputation: 29912

One straightforward method to reach this a "symfonic" way is to use a DataTransformer

DataTransformer will take a data format and transform it into another format (type).

What you can use is a ViewTransformer that, in Transform() phase, will take the entity and return its id whereas in ReverseTransform() it takes the id and, by using a repository, will retrieve Entity.

Something like

class BorrowerToIdTransform implements DataTransformerInterface
{
    private $manager;

    public function __construct(ObjectManager $manager)
    {
        $this->manager = $manager;
    }

    /**
     * Transforms an object (Borrower) to a string (id).
     *
     * @param  Borrower|null $issue
     * @return string
     */
    public function transform($borrower)
    {
        if (null === $borrower) {
            return '';
        }

        return $borrower->getId();
    }

    /**
     * Transforms a string (id) to an object (Borrower).
     *
     * @param  string $id
     * @return Borrower|null
     * @throws TransformationFailedException if object (issue) is not found.
     */
    public function reverseTransform($id)
    {
        if (!$id) {
            return;
        }

        $borrower = $this->manager
            ->getRepository(Borrower::class)
            ->find($id)
        ;

        if (null === $borrower) {
            throw new TransformationFailedException(sprintf(
                'A borrower with "%s" id does not exist!',
                $id
            ));
        }

        return $issue;
    }
}

Upvotes: 1

Ollie in PGH
Ollie in PGH

Reputation: 2629

The "$event->getData()" is your actual entity, if this form uses a default entity in its options resolver or if you pass an entity in through your controller when you make the form.

public function buildForm(FormBuilderInterface $builder, array $options)
 {
    $builder->add('credit');
    $builder->add('currency', 'currency');
    $builder->add('borrower', BorrowerType::class, [
         'required' => true
    ]);

    $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
        $entity = $event->getData();

         //The following doesn't make a lot of sense
         //The borrower will already be set

        $borrower = $this->em->getReference(Borrower::class, $entity->getBorrower());
        $entity->setBorrower($borrower);
    });
 }

Like in this standard way of checking whether a user has to enter a password (if they're new) or if it's not required if the user already exists.

$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
        $user = $event->getData();
        $form = $event->getForm();
        $formParams = [
            'type' => PasswordType::class,
            'first_options' => ['label' => 'Password'],
            'second_options' => ['label' => 'Repeat Password'],
        ];

        if ((!$user || null === $user->getId())) {
            $formParams['constraints'] = new NotBlank();
        } else {
            $formParams['required'] = false;
        }

        $form->add('plainPassword', RepeatedType::class, $formParams);
    });

If this form is creating or updating an entity then the borrower information is set to the entity when it's created.

Upvotes: 0

Related Questions