繁体   English   中英

如何在Sonata Admin中的嵌入式Admin类中获取子对象?

[英]How to get child object in embedded Admin class in Sonata Admin?

我正在尝试获取和操纵与SonataAdmin中的ImageAdmin类相关的实际对象(使用Symfony 2.3)。 当ImageAdmin类是唯一使用的类时,这很好。 但是当ImageAdmin嵌入另一个管理员时,它出现了可怕的错误。

当您没有嵌入式管理员时,这是有效的:

class ImageAdmin extends Admin {
    protected $baseRoutePattern = 'image';

    protected function configureFormFields(FormMapper $formMapper) {
        $subject = $this->getSubject();
    }
}

但是当您使用以下方法在ParentAdmin中嵌入ImageAdmin时:

class PageAdmin extends Admin {
    protected function configureFormFields(FormMapper $formMapper) {
        $formMapper->add('image1', 'sonata_type_admin');
    }
}

然后,当您编辑ID为10的父项并在ImageAdmin中调用getSubject()时,您将获得ID为10的图像

换句话说,getSubject()从URL中提取id,然后调用$this->getModelManager()->find($this->getClass(), $id); ,它交叉引用Parent id和Image id。 哎呀!


所以...我想要做的是能够掌握当前ImageAdmin实例中正在渲染/编辑的实际对象,无论是直接编辑还是通过嵌入的表单编辑,然后能够做到它。

也许getSubject()是错误的树,但我注意到$this->getCurrentChild()从ImageAdmin :: configureFormFields()调用时返回false,即使使用sonata_type_admin字段类型嵌入ImageAdmin也是如此。 我很困惑......

无论如何,我希望有可能以一种我忽略的显而易见的方式抓住这个对象,这里有人可以帮助启发我!

感谢Tautrimas的一些想法,但我设法找到了答案:

在ImageAdmin中设置:

protected function configureFormFields(FormMapper $formMapper)
{
    if($this->hasParentFieldDescription()) { // this Admin is embedded
        $getter = 'get' . $this->getParentFieldDescription()->getFieldName();
        $parent = $this->getParentFieldDescription()->getAdmin()->getSubject();
        if ($parent) {
          $image = $parent->$getter();
        } else {
          $image = null;
        }
    } else { // this Admin is not embedded
        $image = $this->getSubject();
    }

    // You can then do things with the $image, like show a thumbnail in the help:
    $fileFieldOptions = array('required' => false);
    if ($image && ($webPath = $image->getWebPath())) {
        $fileFieldOptions['help'] = '<img src="'.$webPath.'" class="admin-preview" />';
    }

    $formMapper
        ->add('file', 'file', $fileFieldOptions)
    ;
}

我很快就会在即将推出的SonataAdmin烹饪书中发布这个!

https://github.com/sonata-project/SonataAdminBundle/issues/1546

caponica的解决方案只适用于oneOoOne关系,对吗? 在我的oneToMany案例中,这个:$ parent - > $ getter()返回一个集合,我不知道如何识别当前主题。 我发现了这个错误报告: https//github.com/sonata-project/SonataAdminBundle/issues/1568 ,其中包含一个修复程序,但它仍然是打开的,所以我希望他们很快合并:(

编辑

通过一些研究,有一个临时的解决方法: 修复了sonata_type_collection中的错误主题

简而言之:

创建一个类并复制该文件的内容: AdminType然后将其添加到services.yml中,并将类命名空间更改为新的类命名空间:

services:
sonata.admin.form.type.admin:
    class: ACME\AdminBundle\Form\Type\AdminType
    tags:
        - { name: form.type, alias: sonata_type_admin }

它仍然有一个bug:

当在父文档和嵌入表单中启用cascade_validation有错误时,也修复不起作用

你能试试$this->getForm()->getViewData(); 你的ImageAdmin? 这应该会为您提供正确的子实体。

我尝试了所有这些解决方案,但没有一个证明可行。
所以,我努力寻找解决方案。 我的解决方案基于caponica的解决方案,但是在oneToMany案例上工作。 我找到的解决方案是一种解决方法,但效果很好。
它正在使用会话。

public function getCurrentObjectFromCollection($adminChild)
    {
    $getter = 'get' . $adminChild->getParentFieldDescription()
                               ->getFieldName();
    $parent = $adminChild->getParentFieldDescription()
                   ->getAdmin()
                   ->getSubject();
    $collection = $parent->$getter();

    $session = $adminChild->getRequest()->getSession();
    $number = 0;
    if ($session->get('adminCollection')) {
        $number = $session->get('adminCollection');
        $session->remove('adminCollection');
    }
    else {
        $session->set('adminCollection', 1 - $number);
    }

    return $collection[$number];
}

并且您通过以下方式获得管理员中的正确对象:

    $object = $this->getCurrentObjectFromCollection($this)

因此,当父级需要显示子管理员列表时,每个子管理员都将运行此功能并更新会话参数。 获取所有元素后,将删除会话参数。
此代码仅适用于包含2个元素的列表,但可以针对任意数量的元素进行更新。

希望这有助于某人:)

我有同样的问题,我可以通过“自定义表单类型扩展”执行此操作,其文档在链接“ http://symfony.com/doc/current/cookbook/form/create_form_type_extension.html ”上给出。

这是完美的解决方案..

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM