【问题标题】:Create form from variable classnames with parameters从带有参数的变量类名创建表单
【发布时间】:2017-05-20 15:07:02
【问题描述】:

我有一个控制器可以使用变量类名为用户提供正确的表单类型。

有一个名为 EntityForm 的实体,它存储所有可用表单的数据,以及提供类名和表单类型名称的方法:

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
/**
 * @ORM\Entity
 * @ORM\Table(name="entity_form")
 */
class EntityForm
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(length=12)
     */
    protected $url;


    /**
     * @var string
     *
     * @ORM\Column
     */
    protected $name;

    /**
     * @var string
     *
     * @ORM\Column(name="class_name")
     */
    protected $className;

    /**
     * @var string
     *
     * @ORM\Column(name="description")
     */
    protected $description;

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

    /**
     * Set url
     *
     * @param string $url
     *
     * @return Form
     */
    public function setUrl($url)
    {
        $this->url = $url;

        return $this;
    }

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

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Form
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    /**
     * Set className
     *
     * @param string $className
     *
     * @return Form
     */
    public function setClassName($className)
    {
        $this->className = $className;

        return $this;
    }

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

    public function createEntity()
    {
        $entity = sprintf('%s\%s', __NAMESPACE__, $this->getClassName());

        return new $entity;
    }

    public function createType()
    {
        return sprintf('AppBundle\Form\%sType', $this->getClassName());
    }
    /**
     * Set description
     *
     * @param string $description
     *
     * @return Form
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

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

创建正确表单的操作如下所示:

/**
 * @Route("/form/ent/{url}", name="entity_form")
 * @Method("GET")
 */
public function formAction(EntityForm $entityForm)
{

    $form = $this->createForm($entityForm->createType())
        ->add('Dodaj!', SubmitType::class, array(
            'attr' => array(
                'class' => 'btn-info'
            )
        ))
    ;

    return $this->render('default/form.html.twig', [
        'form_name' => $entityForm->getName(),
        'form_description' => $entityForm->getDescription(),
        'form' => $form->createView(),
    ]);
}

此控制器链接到正确的表单类型,即。对于循环通讯

class CyclicNewsletterType extends AbstractType
{
    private $doctrine;

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

    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $currencies = $this->doctrine->getRepository('AppBundle:Currency')->findAll();
        $currenciesFormat = array();

        foreach($currencies as $currency){
            $currenciesFormat += array($currency->getName() .' ('. $currency->getShortName() . ')' => $currency);
        }

        $cycles = $this->doctrine->getRepository('AppBundle:Cycle')->findAll();
        $cyclesFormat = array();

        foreach($cycles as $cycle){
            $cyclesFormat += array($cycle->getName() => $cycle);
        }

        $builder
            ->add('currency', ChoiceType::class, array(
                'label' => 'Waluta',
                'choices' => $currenciesFormat,
            ))
            ->add('cycle', ChoiceType::class, array(
                'label' => 'Cykl',
                'choices' => $cyclesFormat,
            ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => CyclicNewsletter::class,
        ));
    }
}

现在通过一个简单的 POST 操作,我可以轻松地将新值添加到数据库中,而无需为所有表单编写单独的操作:

/**
 * @Route("/form/ent/{url}", name="form_entity_post")
 * @Method("POST")
 *
 */
public function formPostAction(EntityForm $entityForm, Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $form = $this->createForm($entityForm->createType())
        ->add('Dodaj!', SubmitType::class)
    ;

    $form->handleRequest($request);

    if($form->isSubmitted() && $form->isValid()){
        $formData = $form->getData();


        $formData->setUser($this->container->get('security.token_storage')->getToken()->getUser());
        $em->persist($formData);
        $em->flush();

        return $this->redirectToRoute('form_complete', ['url' => $entityForm->getUrl(), 'entityId' => $formData->getId()]);
    }
    var_dump('problem ' . $form->getErrors());
    exit;
}

然而

我似乎无法获得将已创建的对象注入表单构建器进行编辑的方法。

我的意思是编写一个带有变量类名的表单创建,该变量类名也将存储一个实体实例,这些值将已经在表单中设置。

在 symfony 中可以这样吗?

【问题讨论】:

  • 您能尽量减少代码量吗?太长了。

标签: php forms symfony oop


【解决方案1】:

您需要将您正在编辑的实体的 id 添加到您的 url 中,并将其设为可选。

* @Route("/form/ent/{url}/{id}", name="form_entity_post",  defaults={"id" = null})

在您的控制器中,当您构建表单时,您需要从数据库中获取该对象并将其作为第二个参数传递给 createForm 方法。

/**
 * @Route("/form/ent/{url}/{id}", name="form_entity_post",  defaults={"id" = null})
 * @Method("POST")
 *
 */
public function formPostAction(EntityForm $entityForm, Request $request, $id)
{
    $em = $this->getDoctrine()->getManager();

    $entity = null;
    if ($id) {
       $entity = $em->getRepository($entityForm->getClassName)->find($id);
    }

    $form = $this->createForm($entityForm->createType(), $entity)
        ->add('Dodaj!', SubmitType::class)
    ;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 2014-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多