Symfony 4 覆盖 Sonata Admin CRUD 控制器

Posted

技术标签:

【中文标题】Symfony 4 覆盖 Sonata Admin CRUD 控制器【英文标题】:Symfony 4 override Sonata Admin CRUD Controller 【发布时间】:2018-12-12 01:22:05 【问题描述】:

在 Symfony 4 上覆盖 Sonata Admin 的 editAction 时遇到问题。 我的问题是我有这个用于编辑帖子的界面,你可以看到这两张图片:

Everytime The admin change the content formatter it get changed and the changes get saved in mysql

but when you try to edit the post again the admin get always 'text' selected by default

我想让默认选择的选项保存在 MySQL 中。 例如,如果管理员将其更改为rawhtml,下次当他要编辑此帖子时,他应该会找到默认选中的rawhtml(不是图片中的文字)。

这是奏鸣曲editAction方法:

public function editAction($id = null)

    $request = $this->getRequest();
    // the key used to lookup the template
    $templateKey = 'edit';

    $id = $request->get($this->admin->getIdParameter());
    $existingObject = $this->admin->getObject($id);

    if (!$existingObject) 
        throw $this->createNotFoundException(sprintf('unable to find the object with id: %s', $id));
    

    $this->checkParentChildAssociation($request, $existingObject);

    $this->admin->checkAccess('edit', $existingObject);

    $preResponse = $this->preEdit($request, $existingObject);
    if (null !== $preResponse) 
        return $preResponse;
    

    $this->admin->setSubject($existingObject);
    $objectId = $this->admin->getNormalizedIdentifier($existingObject);

    /** @var $form Form */
    $form = $this->admin->getForm();
    $form->setData($existingObject);
    $form->handleRequest($request);
    if ($form->isSubmitted()) 
        $isFormValid = $form->isValid();

        // persist if the form was valid and if in preview mode the preview was approved
        if ($isFormValid && (!$this->isInPreviewMode() || $this->isPreviewApproved())) 
            $submittedObject = $form->getData();
            $this->admin->setSubject($submittedObject);

            try 
                $existingObject = $this->admin->update($submittedObject);

                if ($this->isXmlHttpRequest()) 
                    return $this->renderJson([
                        'result' => 'ok',
                        'objectId' => $objectId,
                        'objectName' => $this->escapeHtml($this->admin->toString($existingObject)),
                    ], 200, []);
                

                $this->addFlash(
                    'sonata_flash_success',
                    $this->trans(
                        'flash_edit_success',
                        ['%name%' => $this->escapeHtml($this->admin->toString($existingObject))],
                        'SonataAdminBundle'
                    )
                );

                // redirect to edit mode
                return $this->redirectTo($existingObject);
             catch (ModelManagerException $e) 
                $this->handleModelManagerException($e);

                $isFormValid = false;
             catch (LockException $e) 
                $this->addFlash('sonata_flash_error', $this->trans('flash_lock_error', [
                    '%name%' => $this->escapeHtml($this->admin->toString($existingObject)),
                    '%link_start%' => '<a href="'.$this->admin->generateObjectUrl('edit', $existingObject).'">',
                    '%link_end%' => '</a>',
                ], 'SonataAdminBundle'));
            
        

        // show an error message if the form failed validation
        if (!$isFormValid) 
            if (!$this->isXmlHttpRequest()) 
                $this->addFlash(
                    'sonata_flash_error',
                    $this->trans(
                        'flash_edit_error',
                        ['%name%' => $this->escapeHtml($this->admin->toString($existingObject))],
                        'SonataAdminBundle'
                    )
                );
            
         elseif ($this->isPreviewRequested()) 
            // enable the preview template if the form was valid and preview was requested
            $templateKey = 'preview';
            $this->admin->getShow();
        
    

    $formView = $form->createView();
    // set the theme for the current Admin Form
    $this->setFormTheme($formView, $this->admin->getFormTheme());

    // NEXT_MAJOR: Remove this line and use commented line below it instead
    $template = $this->admin->getTemplate($templateKey);
    // $template = $this->templateRegistry->getTemplate($templateKey);

    return $this->renderWithExtraParams($template, [
        'action' => 'edit',
        'form' => $formView,
        'object' => $existingObject,
        'objectId' => $objectId,
    ], null);

这是我用于 PostAdmin 的 configureFormFields 方法:

        $isHorizontal = 'horizontal' == $this->getConfigurationPool()->getOption('form_type');
    $formMapper
        ->with('group_post', [
            'class' => 'col-md-8',
        ])
        ->add('author', ModelListType::class)
        ->add('title')
        ->add('abstract', TextareaType::class, [
            'attr' => ['rows' => 5],
        ])
        ->add('content', FormatterType::class, [
            'event_dispatcher' => $formMapper->getFormBuilder()->getEventDispatcher(),
            'format_field' => 'contentFormatter',
            'source_field' => 'rawContent',
            'source_field_options' => [
                'horizontal_input_wrapper_class' => $isHorizontal ? 'col-lg-12' : '',
                'attr' => ['class' => $isHorizontal ? 'span10 col-sm-10 col-md-10' : '', 'rows' => 20],
            ],
            'ckeditor_context' => 'news',
            'target_field' => 'content',
            'listener' => true,
        ])
        ->end()
        ->with('group_status', [
            'class' => 'col-md-4',
        ])
        ->add('enabled', CheckboxType::class, ['required' => false])
        ->add('image', ModelListType::class, ['required' => false], [
            'link_parameters' => [
                'context' => 'news',
                'hide_context' => true,
            ],
        ])

        ->add('publicationDateStart', DateTimePickerType::class, [
            'dp_side_by_side' => true,
        ])
        ->add('commentsCloseAt', DateTimePickerType::class, [
            'dp_side_by_side' => true,
            'required' => false,
        ])
        ->add('commentsEnabled', CheckboxType::class, [
            'required' => false,
        ])
        ->add('commentsDefaultStatus', CommentStatusType::class, [
            'expanded' => true,
        ])
        ->end()

        ->with('group_classification', [
            'class' => 'col-md-4',
        ])
        ->add('tags', ModelAutocompleteType::class, [
            'property' => 'name',
            'multiple' => 'true',
            'required' => false,
        ])
        ->add('collection', ModelListType::class, [
            'required' => false,
        ])->end();
    $options = $formMapper->get('content')->get('contentFormatter')->getOptions();
    $options = array_merge($options,array('choices'=>array('markdown'=>'markdown','text'=>'text','rawhtml'=>'rawhtml','richhtml'=>'richhtml')));
    $rawcontent = $formMapper->get('content')->get('rawContent');
    $formMapper->get('content')->remove('contentFormatter')->remove('rawContent')->add('contentFormatter',ChoiceType::class,$options)->add($rawcontent);

它仍然不采用默认选择值。 反正有没有强迫它从mysql中获取真正的价值作为“数据”? 我找不到应该在哪里编辑表单以从对象中获取默认选定值。如果你能帮我解决这个问题,我会很高兴的。我不熟悉 Sonata 捆绑包和管理表单。

【问题讨论】:

您从不使用 $options 变量...表示您的实体的 contentFomatter 属性的表单字段在哪里? 【参考方案1】:

我认为根本不需要修改editAction或控制器。

我想让默认选择的选项保存在 MySQL 中。

这是将值从表单保存回模型并在下次编辑时显示的经典用例。

你应该修改你的管理类

我不知道您的模型,但例如在您的管理员configureFormFields 方法中:

$formMapper->add('contentFormatter', 'choice', ['choices' => ['Text' => 'text', 'Raw HTML' => 'rawHtml']]);

所以选择的格式为 Display Value => Value from the entity。

因此,如果您的实体值返回“rawHtml”,表单将选择“原始 HTML”。如果这不起作用,则说明您的管理员配置错误。仔细检查您的实体对象返回的值。

【讨论】:

对不起@Jim 看我已经为 UserAdmin 类添加了 configureFormFields,我是否也应该为 PostAdmin 添加它? `` 抱歉,您的原始帖子中没有添加任何内容...您在哪里添加的? 看看这是我的 UserAdmin 的 configureFormFields 方法:`protected function configureFormFields(FormMapper $formMapper) :void if ($this-&gt;getFormAction() == 'create') $formMapper -&gt;add('email', null, ['attr' =&gt; ['placeholder' =&gt; 'Email']]) -&gt;add('plainPassword', TextType::class, [ 'attr' =&gt; [ 'class' =&gt; 'password-generator-input', 'placeholder' =&gt; 'Password', ] ]) PostAdmin 我也应该这样做吗? 能否将其添加到您的原始帖子中? 完成。是的,我能够使用 configureFormFields 操作表单,但我无法强制它将保存的值作为默认选择。这就是我想覆盖 editAction 的原因,因为我将可以访问该对象,然后我可以强制contentFormatter 从对象中获取默认值,如下所示:array('choices'=&gt;array('markdown'=&gt;'markdown','text'=&gt;'text','rawhtml'=&gt;'rawhtml','richhtml'=&gt;'richhtml'),'data'=&gt;$existingObject-&gt;getContentFormatter()));

以上是关于Symfony 4 覆盖 Sonata Admin CRUD 控制器的主要内容,如果未能解决你的问题,请参考以下文章

在 Symfony 4 上的 Sonata 管理页面中创建一个新页面

在Symfony 4上的Sonata管理页面中创建新页面

Symfony - Sonata-Admin 菜单组翻译

Symfony 3 Sonata Admin 使用注释创建管理员

Symfony - Sonata Abstract Admin 和 getDoctrine

Symfony 3 上的 Sonata Admin 实体翻译