Php Symfony 2:多表单生成的对象列表

Php Symfony 2:多表单生成的对象列表,php,forms,symfony,Php,Forms,Symfony,我想生成一个带有用户名列表的页面,在每个我想要的用户旁边都有一个按钮,可以激活/停用这个用户 当然,我可以使用用户ID创建链接,并在控制器中获取方法,该方法将在单击链接时执行操作。据我所知,出于安全考虑,不建议这样做。所以,我希望有表单和按钮来提交请求,以放置将改变用户状态的路由,而不是执行操作的路由链接 问题:如何根据Doctrine返回的用户列表生成此类表单(按钮) 用于在用户配置文件中创建表单/按钮的表单代码: /** * Creates a form to activate/d

我想生成一个带有用户名列表的页面,在每个我想要的用户旁边都有一个按钮,可以激活/停用这个用户

当然,我可以使用用户ID创建链接,并在控制器中获取方法,该方法将在单击链接时执行操作。据我所知,出于安全考虑,不建议这样做。所以,我希望有表单和按钮来提交请求,以放置将改变用户状态的路由,而不是执行操作的路由链接

问题:如何根据Doctrine返回的用户列表生成此类表单(按钮)

用于在用户配置文件中创建表单/按钮的表单代码:

    /**
 * 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控制台操作自动生成它。如果我需要很多这样的按钮,我简直找不到地方该怎么办。