简体   繁体   中英

Symfony 2 Create Dynamic Forms

I'd like to create a form that allows the user to subscribe/unsubscribe from a variety of topics stored in a database. Basically, all topics available are stored and need to be output with a checkbox so the user may add/remove that topic from their profile. I've done this with vanilla PHP easily but am new to Symfony2. Here's what I have so far.

I think I've created the form correctly but I'm not exactly sure how to write the controller here. This is just a little test to see how to do it and in this case, the col that holds the topics is called options. Any help would be appreciated. Thank you in advance!

In short, I need to list all vals in the options col as a list of checkboxes.

FormCheck.php

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * FormCheck
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class FormCheck
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="options", type="string", length=255)
     */
    private $options;


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set options
     *
     * @param string $options
     * @return FormCheck
     */
    public function setOptions($options)
    {
        $this->options = $options;

        return $this;
    }

    /**
     * Get options
     *
     * @return string 
     */
    public function getOptions()
    {
        return $this->options;
    }
}

FormCheckType.php

<?php

namespace AppBundle\Form;

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

class FormCheckType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('item', 'entity', array(
            'class'    => 'AppBundle:FormCheck',
            'property' => 'options',
            'expanded' => true,
            'multiple' => true,
        ));
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\FormCheck'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'appbundle_formcheck';
    }
}

FormCheckController.php

<?php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class FormCheckController extends Controller
{
    /**
     * @Route("/form")
     * @Template()
     */
    public function formAction()
    {
        return $this->render('default/formCheck.html.twig');
    }

}

Firstly, you should read the documentation thoroughly, almost everything is covered in there you need.

You would be better off having a User entity and a Topic entity to store your topics and to join them with a many to many relationship.

This way you can add/remove topics & your form will update, and you won't have duplicated information across the options string in each user.

Eg (I have not syntax checked this at all, there may be typos, but this is the general gist of what I'd do in your situation)

User

/**
 * @var string
 *
 * @ORM\ManyToMany(targetEntity="YourNamespace\YourBundle\Entity\Topic", mappedBy="users")
 */
protected $topics;

Topic

/**
 * @ORM\ManyToMany(targetEntity="YourNamespace\YourBundle\Entity\User", inversedBy="topics")
 * @ORM\JoinTable(name="user_topic",
 *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="topic_id", referencedColumnName="id")}
 *      )
 */
protected $users;

Form

class UserTopicType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('topics', 'entity', array(
            'class'    => 'AppBundle:Topic',
            'property' => 'topics',
            'expanded' => true,
            'multiple' => true,
        ));
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\User'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'appbundle_usertopic';
    }
}

Controller

class FormCheckController extends Controller
{
    /**
     * @Route("/form")
     * @Template()
     */
    public function formAction(Request $request)
    {
        $user = // however you get your user here

        $form = $this->createForm(new UserTopicType(), $user);
        $formView = $form->createView();

        $form->handleRequest($request); // request 

        if ($form->isValid()) {

          // persist, flush your user here and redirect to your form
          // or whatever you want to do
        }

        $parameters = array(
            'form' => $formView,
        );

    return $this->render('default/formCheck.html.twig', $parameters);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM