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

时间:2013-08-07 14:45:11

标签: symfony 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()是一个错误的树,但是我注意到{Image:}在从ImageAdmin :: configureFormFields()调用时返回false,即使使用sonata_type_admin字段类型嵌入了ImageAdmin也是如此。我很困惑......

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

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

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

修改

通过一些研究,可以暂时解决这个问题:Fixed getting wrong subject in 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时出错也无法解决

答案 2 :(得分:0)

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

答案 3 :(得分: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个元素的列表,但可以针对任意数量的元素进行更新。

希望这有助于某人:)

答案 4 :(得分:0)

我有同样的问题,我可以通过&#34;自定义表格类型扩展&#34;在链接上提供了哪些文档&#34; http://symfony.com/doc/current/cookbook/form/create_form_type_extension.html&#34;

这是完美的解决方案..