5

我正在尝试获取和操作与 SonataAdmin 中的 ImageAdmin 类相关的实际对象(使用 Symfony 2.3)。当 ImageAdmin 类是唯一被使用的类时,这可以正常工作。但是当 ImageAdmin 被嵌入到另一个 Admin 中时,它就出现了可怕的错误。

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

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

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

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

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,即使 ImageAdmin 是使用 sonata_type_admin 字段类型嵌入的。我很困惑...

无论如何,我希望有可能以某种我忽略的明显方式来获取该对象,并且这里有人可以帮助启发我!

4

5 回答 5

13

感谢 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

于 2013-08-09T12:29:09.590 回答
2

caponica 的解决方案仅适用于 oneToOne 关系,对吗?在我的 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 }

但它仍然有一个错误:

还修复在父文档中启用 cascade_validation 并且嵌入表单有错误时不起作用

于 2014-04-02T14:54:26.123 回答
0

我尝试了所有这些解决方案,但没有一个被证明有效。
所以,我努力寻找解决方案。我的解决方案基于 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 个元素的列表,但可以针对任意数量的元素进行更新。

希望这可以帮助某人:)

于 2014-04-25T09:25:34.980 回答
0

$this->getForm()->getViewData();您可以在 ImageAdmin 中尝试吗?这应该为您提供正确的子实体。

于 2013-08-08T11:26:53.997 回答
0

我有同样的问题,我可以通过“自定义表单类型扩展”来做到这一点,链接“ http://symfony.com/doc/current/cookbook/form/create_form_type_extension.html ”上给出了文档。

这是完美的解决方案..

于 2014-07-04T04:03:06.980 回答