Symfony 2:多种形式生成的对象列表 [英] Symfony 2: Multiple forms generated list of objects
问题描述
我想生成包含用户名列表的页面,并且在每个用户旁边我想有一个按钮来激活/停用该用户.
I would like to generate page with list of users names and next to every user I would like to have button which would activate/deactivate this user.
我当然可以在控制器中创建带有用户 ID 和 GET 方法的链接,当点击链接时,它会执行操作.据我所知,出于安全考虑,不建议这样做.因此,我希望使用表单和按钮来向 PUT 路由提交请求,从而更改用户状态,而不是链接到执行操作的路由.
I could of course create link with user ID and GET method in controller which would perform operation when link would be clicked. As far as I know it is not recommended though to do it this way due to security concerns. So instead of links to route which would perform operation I would like to have forms and buttons to submit request to PUT route which would change user status.
问题:如何根据 Doctrine 返回的用户列表生成此类表单(按钮)?
QUESTION: how to generate such forms (buttons) based on list of users returned by Doctrine?
用于在用户配置文件中创建表单/按钮的表单代码:
Form code used to create form/button in user profile:
/**
* Creates a form to activate/deactivate a User entity by id.
*
* @param mixed $id The entity id
*
* @return \Symfony\Component\Form\Form The form
*/
private function createActivationDeactivationForm($id)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('user_activate', array('id' => $id)))
->setMethod('PUT')
->add('submit', 'submit', array('label' => 'Activate/Deactivate'))
->getForm()
;
}
用于用户配置文件的控制器代码:
Controller code used for user profile:
/**
* @Route("/user/{id}", name="user_show")
* @Method("GET")
* @Template()
*/
public function showUserAction($id)
{
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('TestUserBundle:User')->find($id);
if (!$user) {
throw $this->createNotFoundException('Unable to find user');
}
$deleteForm = $this->createDeleteForm($id);
$activateForm = $this->createActivationDeactivationForm($id);
return array(
'user' => $user,
'delete_form' => $deleteForm->createView(),
'activate_form' => $activateForm->createView(),
);
}
从用户配置文件执行操作的控制器 PUT 方法:
Controller PUT method to perform operation from user profile:
/**
* Activate a user.
*
* @Route("/{id}", name="user_activate")
* @Method("PUT")
*/
public function activateAction(Request $request, $id)
{
$form = $this->createActivationDeactivationForm($id);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('TestUserBundle:User')->find($id);
if (!$user) {
throw $this->createNotFoundException('Unable to find user');
}
$current_user_activity_flag = $user->getActive();
$user->setActive(abs($current_user_activity_flag-1));
$em->persist($user);
$em->flush();
}
return $this->redirect($this->getRequest()->headers->get('referer'));
}
用于用户列表的控制器代码:
Controller code to be used for users list:
/**
* @Route("/users", name="users_list")
* @Method("GET")
* @Template()
*/
public function listUsersAction()
{
$em = $this->getDoctrine()->getManager();
$users = $em->getRepository('TestUserBundle:User')->findExistingUsers();
//$deleteForm = $this->createDeleteForm($id);
//$activateForm = $this->createActivationDeactivationForm($id);
return array(
'users' => $users,
//'delete_form' => $deleteForm->createView(),
//'activate_form' => $activateForm->createView(),
);
}
我无法将 ID 传递给表单,就像我从配置文件操作时所做的那样,因为每个用户都有不同的 ID,而且更多的是 Symfony 只生成第一个表单并忽略其余部分.
I can not pass ID to form like I did for operation from profile cause for every user there is different ID and more of that Symfony generates only first form and ignores rest.
知道如何处理吗?或者我对表单/按钮的处理方式不正确,我应该只使用链接?
Any idea how to handle it? Or maybe my approach with form/buttons is incorrect and I should just use links instead?
推荐答案
我找到了可行的解决方案,但我不确定它是否符合最佳实践.
I found solution which works though I am not sure about if it's compliant with best practices.
我没有在控制器中传递一个表单对象,而是根据用户 ID 生成了一个带有键的数组.比在 TWIG 模板中循环数组时,我使用用户 ID 来引用为当前用户创建的表单对象.
Instead of passing one form object in controller I generated an array of them with keys based on user ID. Than when looping through array in TWIG template I use user ID to refer form object created for current user.
提到的用户列表问题控制器应该看起来像这样:
Mentioned in question controller for user listing should than look like this:
/**
* @Route("/users", name="users_list")
* @Method("GET")
* @Template()
*/
public function listUsersAction()
{
$em = $this->getDoctrine()->getManager();
$users = $em->getRepository('PSUserBundle:User')->findExistingUsers();
$activate_forms = array();
$delete_forms = array();
foreach($users as $user)
{
$activate_forms[$user->getId()] = $this->createActivationDeactivationForm($user->getId())->createView();
$delete_forms[$user->getId()] = $this->createDeleteForm($user->getId())->createView();
}
return array(
'users' => $users,
'delete_forms' => $delete_forms,
'activate_forms' => $activate_forms,
);
}
... 并且在 foreach 中的 TWIG 形式应该是这样引用的:
... and in TWIG form within foreach should be refered like this:
{{ form_start(activate_forms[user.id], {'attr': {'novalidate': 'novalidate'}}) }}
{% if user.active %}
{{ form_widget(activate_forms[user.id].submit, {'attr': {'class': 'btn btn-xs btn-warning btn-block'}, 'label' : 'Deactivate'}) }}
{% else %}
{{ form_widget(activate_forms[user.id].submit, {'attr': {'class': 'btn btn-xs btn-success btn-block'}, 'label' : 'Activate'}) }}
{% endif %}
{{ form_end(activate_forms[user.id]) }}
这篇关于Symfony 2:多种形式生成的对象列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!