Symfony2实体表单类型获取数据

时间:2015-07-20 08:54:02

标签: forms symfony types get entity

我有2个实体:音频和目的地

在音频中:

/**
     * @ORM\OneToOne(targetEntity="HearWeGo\HearWeGoBundle\Entity\Destination", inversedBy="audio")
     * @Assert\NotBlank(message="This field must be filled")
     * 
     */
    private $destination;

我创建了一个表单类型名称AddAudioType,用于将音频上传到数据库

<?php

namespace HearWeGo\HearWeGoBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use HearWeGo\HearWeGoBundle\Entity\Audio;

class AddAudioType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name','text')
            ->add('content','file')
            ->add('destination','entity',array('class'=>'HearWeGoHearWeGoBundle:Destination','property'=>'name'))
            ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array('data_class'=>"HearWeGo\\HearWeGoBundle\\Entity\\Audio"));
    }

    public function getName()
    {
        return 'add_audio';
    }
}
?>

在控制器

/**
     * @Route("/admin/add/audio",name="add_audio")
     */
    public function addAudioAction(Request $request)
    {
        if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_FULLY')){
            return  new Response('Please login');
        }

        $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');

        $audio=new Audio();
        $form=$this->createForm(new AddAudioType(),$audio,array(
            'method'=>'POST',
            'action'=>$this->generateUrl('add_audio')
        ));
        $form->add('submit','submit');
        if ($request->getMethod()=='POST')
        {
            $form->handleRequest($request);
            if ($form->isValid())
            {
                $destination=$this->getDoctrine()->getRepository('HearWeGoHearWeGoBundle:Destination')
                    ->findByName($form->get('destination')->getData()->getName());
                $audio->setDestination($destination);
                $name=$_FILES['add_audio']['name']['content'];
                $tmp_name=$_FILES['add_audio']['tmp_name']['content'];
                if (isset($name))
                {
                    if (!empty($name))
                    {
                        $location=$_SERVER['DOCUMENT_ROOT']."/bundles/hearwegohearwego/uploads/";
                        move_uploaded_file($tmp_name,$location.$name);
                        $audio->setContent($location.$name);
                        $em=$this->getDoctrine()->getEntityManager();
                        $em->persist($audio);
                        $em->flush();
                        return new Response('Audio '.$audio->getName().' has been created!');
                    }
                }
            }
        }
        return $this->render('@HearWeGoHearWeGo/manage/addAudio.html.twig',array('form'=>$form->createView()));
    }

在AddAudioType中,我声明它从Destination实体表中获取所有记录,并允许用户选择其中一个,然后将其保存到数据库

现在还有另外一件事需要处理:因为Audio和Destination之间的关系是一对一的,所以不允许用户选择已经出现在Audio表中的Destination。现在在AddAudioType中,我不想从Destination表中获取所有记录,但只有一些尚未出现在Audio表中。我该怎么办?

1 个答案:

答案 0 :(得分:1)

在表单构建器中执行时

->add('destination', 'entity', array(
    'class'=>'HearWeGoHearWeGoBundle:Destination',
    'property'=>'name'
));

您说您想要所有可能的Destination实体

如果你想过滤它们,你有两种可能性

第一个(推荐)

编写自己的方法以排除&#34;关联&#34; Destinations DestionationRepositoryDestinationRepository。如果您不知道什么是存储库,或者您不知道如何编写存储库,请参阅此document。方法实现留给你作为练习(不,真的,我不知道所有实体,所以我不能做出任何猜测)

完成此操作后,您必须将setRequired()传递给您的表单,作为选项(必需我想[请参阅下面的//AddAudioType <?php [...] public function buildForm(FormBuilderInterface $builder, array $options) { $destination_repo = $options['dr']; $builder->[...] ->add('destination','entity',array( 'class'=>'HearWeGoHearWeGoBundle:Destination', 'choices'=> $destination_repo->yourCustomRepoFunctionName(), 'property'=>'name')); } $resolver->setRequired(array( 'dr', )); 方法]) ,所以,这样的事情(我将省略无趣的代码)

DestinationRepository

现在您已为表单设置了全部内容,您需要将//In controller you're instatiating your form [...] public function addAudioAction() { [...] $destination_repo = $this->getDoctrine() ->getManager() ->getRepository('HearWeGoHearWeGoBundle:Destination'); $form=$this->createForm(new AddAudioType(), $audio, array( 'method' => 'POST', 'action' => $this->generateUrl('add_audio'), 'dr' => $destination_repo, )); } 传递给您的表单。那你怎么样? 它确实非常简单

NOT IN
只要你写一个好的&#34;过滤器&#34;它就会像魅力一样工作。方法(即:你用Destinations子句排除所有//AddAudioType use Doctrine\ORM\EntityRepository; <?php [...] public function buildForm(FormBuilderInterface $builder, array $options) { $destination_repo = $options['dr']; $builder->[...] ->add('destination','entity',array( 'class'=>'HearWeGoHearWeGoBundle:Destination', 'choices'=> function(EntityRepository $repository) use ($someParametersIfNeeded) { return $repository->createQueryBuilder('d') ->[...];}, 'property'=>'name')); } ,将密钥输入到其他表中)

第二个

您只需将方法写入表格

即可
createQueryBuilder

在第二种情况下,choices也未实现并留给您。您需要记住一件事:->getQuery()需要一个查询构建器,因此请不要致电->getResult()public function findDestinationWithoutAudio() { $query= "SELECT d FROM HearWeGoHearWeGoBundle:Destination d WHERE d NOT IN (SELECT IDENTITY(a.destination) FROM HearWeGoHearWeGoBundle:Audio a)" ; return $this->getEntityManager()->createQuery($query)->getResult(); }

为什么要拳头?

  • 自定义功能应始终保持在回购范围内。因此,您正在将一些代码写入必须存在的位置(请参阅以下各点以了解方法)
  • 因为代码是可重用的(DRY原则)
  • 因为您可以更轻松地测试代码

自定义回购功能

IDENTITY()

如果您想知道为什么应该直接使用{{1}}函数而不是外键:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#dql-functions