Bap*_*apt 6 php forms performance entity symfony
我有一个包含一些经典字段的表单,以及一个用户实体的下拉列表(使用 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',
))
;
...
}
}
Run Code Online (Sandbox Code Playgroud)
然后我保留整个对象并刷新它。它工作完美。但这个过程实在是太慢了……
当调用 getChoicesForValue 函数 (EntityChoiceList.php) 时,问题来自于 handleRequest 函数。就我而言,该流程对 User 实体执行 findAll() 请求,从数据库中获取所有记录(数千条)。
在此函数中,有一个条件检查 EntityChoiceList 是否具有这样的实体加载器:
if ($this->idAsValue && $this->entityLoader) {
// do a findById()
} else {
// do a findAll()
}
Run Code Online (Sandbox Code Playgroud)
(我确实简化了代码,代码比较复杂,但您可以在 EntityChoiceList.php 文件中找到完整代码)。在调试我的应用程序后,我可以看到 was$this->idAsValue和truewas $this->entityLoader,null解释了为什么它执行 findAll()。
所以我想知道是否有一个选项或任何东西可以使这个过程更快并防止获取所有记录?
谢谢。
编辑 :
我想我可以尝试自己替换 handleRequest 和 Hydro 对象,但我希望有另一种方法来保持经典过程。
最后,我找到了解决方案。我用简单的文本类型替换了实体类型,然后创建了自己的 DataTransformer 类,以便将用户字符串 id 转换为真正的 User 对象。通过这种方式,用户对象可以正确地水合,而无需获取数千条记录,从而显着提高了加载速度。
这正是我所做的:
我变了 :
class MyFormType extends AbstractType{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user', 'entity', array(
'required' => true,
'class' => 'User',
'property' => 'id',
))
;
}
}
Run Code Online (Sandbox Code Playgroud)
到 :
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));
}
}
Run Code Online (Sandbox Code Playgroud)
我创建了自己的 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;
}
}
Run Code Online (Sandbox Code Playgroud)
最后我将 EntityManager 传递给这样的表单:
class MyRestController{
public function MyRestAction(...){
...
$myObject = new MyObject();
$manager = $this->getDoctrine()->getManager();
$myForm = $this->createForm(new MyFormType($manager), $myObject);
$myForm->handleRequest($request);
...
}
}
Run Code Online (Sandbox Code Playgroud)
我在 Symfony 文档中找到了该解决方案: https ://symfony.com/doc/2.7/form/data_transformers.html
它运行完美,现在我的应用程序速度快了 10 倍!
| 归档时间: |
|
| 查看次数: |
655 次 |
| 最近记录: |