Symfony 2.5:实体类型,在提交表单时防止所有记录获取所有记录



我有一个包含一些经典字段的表单,以及一个下拉列表的用户实体列表(使用angularjs处理,而不是经典的表单视图(。当我提交表单时,将通过AJAX请求发送整个对象(以及通过下拉列表选择的用户(发送给我的控制器。

class MyRestController{
    public function MyRestAction(...){
        ...
        $myObject = new MyObject();
        $myForm = $this->createForm(new MyFormType(), $myObject);
        $myForm->handleRequest($request);
        ...
    }
}
class MyFormType extends AbstractType{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add(...),
            ->add(...),
            ->add(...),
            ->add('user', 'entity', array(
                'required' => true,
                'class' => 'User',
                'property' => 'id',
            ))
        ;
            ...
    }
}

然后我坚持整个对象并冲洗它。它可以很好地工作。但是这个过程非常慢...

当调用getChoicesForvalue函数(EntityChoicelist.php(时,问题来自handlequest函数。就我而言,该过程在用户实体上执行findall((请求,从数据库中获取所有记录(千(。

在此功能中,有一个条件检查ENTITYCHOICELIST是否具有这样的EntityLoader:

if ($this->idAsValue && $this->entityLoader) {
    // do a findById()
} else {
    // do a findAll()
}

(我真的简化了代码,这更复杂,但是您可以在EntityChoicelist.php文件中找到整个代码(。在调试我的应用程序之后,我可以看到$this->idAsValuetrue,而$this->entityLoadernull,解释了为什么它可以进行Findall((。

所以我想知道是否有一个选项或其他任何可以使此过程更快的速度并防止获取所有记录?

谢谢。

编辑:

我认为我可以自己替换handlerequest和水合物体,但我希望有另一种方法来保留经典过程。

最后,我找到了一个解决方案。我用简单的文本类型替换了我的实体类型,接下来创建了自己的DataTransformer类,以将用户字符串ID转换为真实的用户对象。通过这种方式,用户对象在不获取数千个记录的情况下正确水合,从而显着提高了加载速度。

这正是我所做的:

我更改了:

class MyFormType extends AbstractType{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('user', 'entity', array(
                'required' => true,
                'class' => 'User',
                'property' => 'id',
            ))
        ;
    }
}

to:

class MyFormType extends AbstractType{
    private $manager;
    public function __construct(ObjectManager $manager)
    {
        $this->manager = $manager;
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('user', 'text', array(
                'required' => true,
            ))
        ;
       // we use a specific ModelTransformer (UserTransformer) created by ourself (see below)
       $builder->get('user')->addModelTransformer(new UserTransformer($this->manager));
    }
}

我像这样创建了自己的UserTransFormer类:

class UserTransformer implements DataTransformerInterface
{
    private $manager;
    public function __construct(ObjectManager $manager)
    {
        $this->manager = $manager;
    }
    public function transform($user)
    {
        if (null === $user) {
            return '';
        }
        return $user->getId();
    }
    public function reverseTransform($id)
    {
        if (!$id) {
            return null;
        }
        $user= $this->manager
            ->getRepository(User::class)
            ->find($id)
        ;
        if (null === $user) {
            throw new TransformationFailedException(sprintf(
                'There is no User with the id "%s" !',
                $id
            ));
        }
        return $user;
    }
}

最后,我将EntityManager传递到这样的表格:

class MyRestController{
    public function MyRestAction(...){
        ...
        $myObject = new MyObject();
        $manager = $this->getDoctrine()->getManager();
        $myForm = $this->createForm(new MyFormType($manager), $myObject);
        $myForm->handleRequest($request);
        ...
    }
}

我在此处的Symfony文档中找到了该解决方案: https://symfony.com/doc/2.7/form/data_transformers.html

它可以完美地工作,现在我的应用程序快10倍!

最新更新