Php Symfony 2:多表单生成的对象列表
我想生成一个带有用户名列表的页面,在每个我想要的用户旁边都有一个按钮,可以激活/停用这个用户 当然,我可以使用用户ID创建链接,并在控制器中获取方法,该方法将在单击链接时执行操作。据我所知,出于安全考虑,不建议这样做。所以,我希望有表单和按钮来提交请求,以放置将改变用户状态的路由,而不是执行操作的路由链接 问题:如何根据Doctrine返回的用户列表生成此类表单(按钮) 用于在用户配置文件中创建表单/按钮的表单代码:Php Symfony 2:多表单生成的对象列表,php,forms,symfony,Php,Forms,Symfony,我想生成一个带有用户名列表的页面,在每个我想要的用户旁边都有一个按钮,可以激活/停用这个用户 当然,我可以使用用户ID创建链接,并在控制器中获取方法,该方法将在单击链接时执行操作。据我所知,出于安全考虑,不建议这样做。所以,我希望有表单和按钮来提交请求,以放置将改变用户状态的路由,而不是执行操作的路由链接 问题:如何根据Doctrine返回的用户列表生成此类表单(按钮) 用于在用户配置文件中创建表单/按钮的表单代码: /** * Creates a form to activate/d
/**
* 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()
;
}
/**
* @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(),
);
}
/**
* 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'));
}
用于用户配置文件的控制器代码:
/**
* 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()
;
}
/**
* @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(),
);
}
/**
* 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'));
}
从用户配置文件执行操作的控制器PUT方法:
/**
* 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()
;
}
/**
* @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(),
);
}
/**
* 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'));
}
用于用户列表的控制器代码:
/**
* @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只生成第一个表单,而忽略其余的
你知道怎么处理吗?或者,我使用表单/按钮的方法不正确,我应该使用链接来代替?我找到了有效的解决方案,尽管我不确定它是否符合最佳实践 我没有在控制器中传递一个表单对象,而是根据用户ID生成了一个带有键的表单对象数组。而在TWIG模板中的数组中循环时,我使用用户ID引用为当前用户创建的表单对象 问题中提到的用于用户列表的控制器应如下所示:
/**
* @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,
);
}
{{ 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]) }}
。。。foreach中的细枝形式应如下所示:
/**
* @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,
);
}
{{ 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]) }}
为什么在GET中使用ID来禁用用户会存在安全问题?你总是可以用一个角色来阻止这条路线,并对此进行更多的报道…@Jean:当你使用常规链接来执行操作时,没有使用CSRF令牌,从而使你面临这种攻击。把表单(和提交按钮)放在里面可以利用内置的表单安全机制。啊,你是说XSS攻击吗?您可以避免在被调用的路由中使用表单。如果您愿意,路由可以位于颜色框中,以避免页面导航。总之,一般来说,在一个页面中有许多相同的表单是个坏主意。@Jean:是的,XSS。你的意思是链接到单独的页面,其中有表单/确认框(颜色框)?我更愿意避免这种变通方法,因为将这些按钮放在列表上的想法是让操作“一键点击”,因为这可能是非常常见的(并且在许多不同的情况下,包含要执行的操作的列表可能适用)。我喜欢你不太喜欢的做法,在哪里有按钮,我需要的形式。。。但这似乎是Symfony推荐的方法——他们甚至为CRUD控制台操作自动生成它。如果我需要很多这样的按钮,我简直找不到地方该怎么办。