Php Symfony2:在SonataAdmin中重写createAction()

Php Symfony2:在SonataAdmin中重写createAction(),php,symfony,sonata-admin,Php,Symfony,Sonata Admin,最近几天,我一直在谷歌上疯狂地搜索,试图找出(但没有成功)如何覆盖SonataAdmin操作以捕获会话用户名并将其保存在外键字段中 AttachmentAdminController类: <?php namespace Application\Sonata\UserBundle\Controller; use Sonata\AdminBundle\Controller\CRUDController as Controller; #use Symfony\Bundle\Framework

最近几天,我一直在谷歌上疯狂地搜索,试图找出(但没有成功)如何覆盖SonataAdmin操作以捕获会话用户名并将其保存在外键字段中

AttachmentAdminController类:

<?php

namespace Application\Sonata\UserBundle\Controller;

use Sonata\AdminBundle\Controller\CRUDController as Controller;
#use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use FOS\UserBundle\Entity\User;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Bridge\Monolog\Logger;
use Mercury\CargoRecognitionBundle\Entity\Attachment;

class AttachmentAdminController extends Controller
{
    /**
     * (non-PHPdoc)
     * @see Sonata\AdminBundle\Controller.CRUDController::createAction()
     */
    public function createAction()
    {
        $result = parent::createAction();

        if ($this->get('request')->getMethod() == 'POST')
        {
            $flash = $this->get('session')->getFlash('sonata_flash_success');

            if (!empty($flash) && $flash == 'flash_create_success')
            {
                #$userManager = $this->container->get('fos_user.user_manager');
                #$user = $this->container->get('context.user');
                #$userManager = $session->get('username');
                $user = $this->container->get('security.context')->getToken()->getUser()->getUsername();

                $attachment = new Attachment();
                $attachment->setPath('/tmp/image.jpg');
                $attachment->setNotes('nothing interesting to say');
                $attachment->getSystemUser($user);

                $em = $this->getDoctrine()->getEntityManager();
                $em->persist($product);
                $em->flush();
            }
        }

        return $result;
    }
}
在我看来,actionController()被SonatAdminBundle(可能还有整个类文件)忽略了,因为根本没有错误消息,但我不知道为什么。实际上,我不确定是否从会话中获取用户名


我真的需要一个关于这方面的好教程,但似乎我得到的任何信息在某些方面都是过时的。顺便说一下,我正在使用Symfony 2.0.16,终于找到了解决方案。我肯定还有其他一些方法(比如使用事件侦听器,这似乎更简单),但现在这是我能找到的最好的方法(它可以工作,这才是最重要的)

我试图根据在另一个论坛线程中找到的示例重写
createAction()
,但是我在表中得到了两条记录,而不是一条。最重要的是重写整个action方法并将自定义代码放入其中

控制器

<?php

namespace Mercury\CargoRecognitionBundle\Controller;

use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Bridge\Monolog\Logger;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Application\Sonata\UserBundle\Entity\User;
use Mercury\CargoRecognitionBundle\Entity\Attachment;
use Mercury\CargoRecognitionBundle\Entity\SystemUser;
use Mercury\CargoRecognitionBundle\Repository\SystemUserRepository;

class AttachmentAdminController extends Controller
{
    /**
     * Set the system user ID
     */
    private function updateFields($object)
    {
        $userName = $this->container->get('security.context')
                        ->getToken()
                        ->getUser()
                        ->getUsername();

        $user = $this->getDoctrine()
                    ->getRepository('ApplicationSonataUserBundle:User')
                    ->findOneByUsername($userName);

        $object->setSystemUser($user);

        return $object;
    }

    /**
     * (non-PHPdoc)
     * @see Sonata\AdminBundle\Controller.CRUDController::createAction()
     */
    public function createAction()
    {
        // the key used to lookup the template
        $templateKey = 'edit';

        if (false === $this->admin->isGranted('CREATE')) {
            throw new AccessDeniedException();
        }

        $object = $this->admin->getNewInstance();

        $object = $this->updateFields($object);

        // custom method
        $this->admin->setSubject($object);

        $form = $this->admin->getForm();
        $form->setData($object);

        if ($this->get('request')->getMethod() == 'POST') {
            $form->bindRequest($this->get('request'));

            $isFormValid = $form->isValid();

            // persist if the form was valid and if in preview mode the preview was approved
            if ($isFormValid && (!$this->isInPreviewMode() || $this->isPreviewApproved())) {
                $this->admin->create($object);

                if ($this->isXmlHttpRequest()) {
                    return $this->renderJson(array(
                        'result' => 'ok',
                        'objectId' => $this->admin->getNormalizedIdentifier($object)
                    ));
                }

                $this->get('session')->setFlash('sonata_flash_success','flash_create_success');
                // redirect to edit mode
                return $this->redirectTo($object);
            }

            // show an error message if the form failed validation
            if (!$isFormValid) {
                $this->get('session')->setFlash('sonata_flash_error', 'flash_create_error');
            } elseif ($this->isPreviewRequested()) {
                // pick the preview template if the form was valid and preview was requested
                $templateKey = 'preview';
            }
        }

        $view = $form->createView();

        // set the theme for the current Admin Form
        $this->get('twig')->getExtension('form')->setTheme($view, $this->admin->getFormTheme());

        return $this->render($this->admin->getTemplate($templateKey), array(
            'action' => 'create',
            'form'   => $view,
            'object' => $object,
        ));
    }
}
mercury.cargo_recognition.admin.attachment:
    class: Mercury\CargoRecognitionBundle\Admin\AttachmentAdmin
    tags:
        - { name: sonata.admin, manager_type: orm, group: General, label: Attachments }
    arguments: [ null, Mercury\CargoRecognitionBundle\Entity\Attachment, "MercuryCargoRecognitionBundle:AttachmentAdmin" ]
我从以下站点获取解决方案:

  • ,
  • ,

(和索纳塔项目文档)

用您自己的逻辑只覆盖预创建钩子可能会很有用:

/**
 * This method can be overloaded in your custom CRUD controller.
 * It's called from createAction.
 *
 * @param mixed $object
 *
 * @return Response|null
 */
protected function preCreate(Request $request, $object)
{
}

在这种情况下,附件实体的映射将非常有用。可能无法将用户名用作D2的fk。您可能希望将user.id作为fk。我不确定“映射实体”是什么意思。您在外键中使用user.id是对的,这从一开始就是我主要关心的问题,事实上,我添加了一个条令查询来从会话用户名中查找用户id,它可以工作,但是。。。override createAction()的最后一个问题是,我在表中生成了两个对象和两条记录(一条来自表单的记录,不带FK,另一条硬编码,带FK)。我正在阅读关于使用prePersist()方法的事件侦听器的内容,因为我只需要一条记录,用户ID记录在外键中。
/**
 * This method can be overloaded in your custom CRUD controller.
 * It's called from createAction.
 *
 * @param mixed $object
 *
 * @return Response|null
 */
protected function preCreate(Request $request, $object)
{
}