How to make Select from array in Symfony Entity

DohMoment :

I'm new to symfony and still learning, my question is how do I populate a select drop-down in a form with an static array of choices. Say I have a class named Cake, I'd like to be able to fill a drop-down for the status of Cake from the array statuses created in the same CakeEntity:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\CakeRepository")
 */
class Cake
{
    /**
     * @ORM\Column(type="string", length=50)
     */

    private $status;

    private $statuses = array(
        'not_ready' => 'Not Ready',
        'almost_ready' => 'Almost Ready',
        'ready'=>'Ready',
        'too_late'=>'Too late'
    );
    public function getStatus(): ?string
    {
        return $this->status;
    }

    public function setStatus(string $status): self
    {
        $this->status = $status;
        return $this;
    }

    public function getStatuses()
    {
       return $this->statuses;
    }
}

My Controller looks like:

namespace App\Controller;

use App\Entity\Cake;
use App\Form\CakeType;
use App\Repository\CakeRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;


/**
 * @Route("/cake")
 */
class CakeController extends AbstractController
{
    /**
     * @Route("/new", name="cake_new", methods={"GET","POST"})
     */
    public function new(Request $request): Response
    {
        $cake = new Cake();
        $form = $this->createForm(CakeType::class, $cake);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {

            $cake->setCreatedAt(\DateTime::createFromFormat('d-m-Y', date('d-m-Y')));
            $cake->setCreatedBy(1);
            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->persist($cake);
            $entityManager->flush();

            return $this->redirectToRoute('cake_index');
        }

        return $this->render('cake/new.html.twig', [
            'cake' => $cake,
            'form' => $form->createView(),
        ]);
    }

My CakeEntity:

<?php

namespace App\Form;

use App\Entity\cake;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;

class CakeType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        ->add('status', ChoiceType::class,
            [
                'choices'=>function(?Cake $cake) {
                    return $cake->getStatuses();
                }
            ]);
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Cake::class,
        ]);
    }
}

When trying to browse /cake/new I get the error:

An error has occurred resolving the options of the form "Symfony\Component\Form\Extension\Core\Type\ChoiceType": The option "choices" with value Closure is expected to be of type "null" or "array" or "\Traversable", but is of type "Closure".

Yoshi :

You could declare getStatuses on Cake as static, or use public constants. E.g.:

class Cake
{
    // with static variables

    private static $statuses = [
        'not_ready'    => 'Not Ready',
        'almost_ready' => 'Almost Ready',
        'ready'        => 'Ready',
        'too_late'     => 'Too late',
    ];

    public static function getStatuses()
    {
        return self::$statuses;
    }

    // or with public const

    public const STATUSES = [
        'not_ready'    => 'Not Ready',
        'almost_ready' => 'Almost Ready',
        'ready'        => 'Ready',
        'too_late'     => 'Too late',
    ];
}

This seems reasonable, as the return value is not instance but class specific.


You could then use:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('status', ChoiceType::class, [
        'choices'=> Cake::getStatuses(),
    ]);

    // or

    $builder->add('status', ChoiceType::class, [
        'choices'=> Cake::STATUSES,
    ]);
}

If the choices actually depend on a given Cake instance, you could pass it via the options array or use form events.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=24339&siteId=1