2

I want to count the choice's items after the form has been created. The field is a simple Symfony's choice field with a query_builder to create the items. How can I achieve this?

<?php

class MyController
{
    public function indexAction()
    {
        $form = $this->createForm(new MyFormWithChoiceFieldType());

        // suppose that the field is named by "countries"
        $items = count(???);
    }
}

Thanks in advance.

Tales Santos
  • 232
  • 3
  • 10

2 Answers2

0

Here's how I do this with Categories.

Notice that I have a CategoryRepository. You can use methods from this repository inside the query_builder options in your FormType classes and also in your controller.

My findAllCategories() method returns a query builder object, therefore I can have another method in the repository called countCategories() which returns the scalar count of that same query builder object.

This allows me to access the count method in my controller and makes sure that the couting will be consistent with the query builder I am using to find the categories.

This is a very simple example but it becomes more useful if you have more complex finder methods with joins and where clauses.

In my Controller:

<?php

use Site\FrontendBundle\Form\Type\CategoryType;

public function indexAction()
{
    $em = $this->getDoctrine()->getManager();
    $repo = $em->getRepository('SiteFrontendBundle:Category');

    $form = $this->createForm(new CategoryType());

    $count = $repo->countAllCategories();

    return $this->render('SiteFrontendBundle:Category:count.html.twig', array(
        'form' => $form->createView(),
        'count' => $count
    ));
}

In my Form Type:

<?php

namespace Site\FrontendBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

use Site\FrontendBundle\Repository\CategoryRepository;

class CategoryType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('category', 'entity', array(
                'class' => 'SiteFrontendBundle:Category',
                'property' => 'title',
                'query_builder' => function(CategoryRepository $cr) {
                    return $cr->findAllCategories();
                }
            ))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Site\FrontendBundle\Entity\Category'
        ));
    }

    public function getName()
    {
        return 'category_type';
    }
}

and in my Category Repository:

<?php

namespace Site\FrontendBundle\Repository;

use Doctrine\ORM\EntityRepository;

class CategoryRepository extends EntityRepository
{
    public function findAllCategories()
    {
        return $this->createQueryBuilder('c')
            ->orderBy('c.lft', 'ASC')
        ;
    }

    public function countAllCategories()
    {
        return $this
            ->findAllCategories()
            ->select('COUNT(c.id)')
            ->getQuery()
            ->getSingleScalarResult()
        ;
    }
}

If you have any questions let me know.

  • Hi Williams, thanks for your reply. I've found a solution that access directly the **choice_list** option of that field. `$form->get("field_name")->getConfig()->getOption('choice_list')->getChoices()`, but this results in a second access to database. Your solution also makes two requests to database, but only for count how many categories are available. I'll keep with your solution until someone suggests a better way to do this. I still think that there is a elegant way to accomplish this. Thx – Tales Santos Jul 24 '13 at 19:40
0

If you need to check in twig:

form.countries.vars.choices|length

Replace countries with the right form field name.

PierrickM
  • 656
  • 6
  • 14