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".
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With