简体   繁体   English

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

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

I'm trying to get and manipulate the actual object related to a ImageAdmin class in SonataAdmin (using Symfony 2.3). 我正在尝试获取和操纵与SonataAdmin中的ImageAdmin类相关的实际对象(使用Symfony 2.3)。 This works fine when the ImageAdmin class is the only one being used. 当ImageAdmin类是唯一使用的类时,这很好。 But when ImageAdmin is embedded in another Admin it goes horribly wrong. 但是当ImageAdmin嵌入另一个管理员时,它出现了可怕的错误。

Here's what works when you don't have embedded Admins: 当您没有嵌入式管理员时,这是有效的:

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

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

But when you embed ImageAdmin in ParentAdmin using this: 但是当您使用以下方法在ParentAdmin中嵌入ImageAdmin时:

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

Then when you're editing a Parent item with id 10 and call getSubject() in ImageAdmin you get the Image with id 10! 然后,当您编辑ID为10的父项并在ImageAdmin中调用getSubject()时,您将获得ID为10的图像

In other words getSubject() extracts the id from the URL then calls $this->getModelManager()->find($this->getClass(), $id); 换句话说,getSubject()从URL中提取id,然后调用$this->getModelManager()->find($this->getClass(), $id); , which cross-references the Parent id and the Image id. ,它交叉引用Parent id和Image id。 Oops! 哎呀!


So... what I want to do is be able to get hold of the actual object that is being rendered/edited in the current ImageAdmin instance, whether it's being edited directly or via an embedded form, and then be able to do things with it. 所以...我想要做的是能够掌握当前ImageAdmin实例中正在渲染/编辑的实际对象,无论是直接编辑还是通过嵌入的表单编辑,然后能够做到它。

Maybe getSubject() is the wrong tree to be barking up, but I note that $this->getCurrentChild() returns false when called from ImageAdmin::configureFormFields(), even when that ImageAdmin is embedded using the sonata_type_admin field type. 也许getSubject()是错误的树,但我注意到$this->getCurrentChild()从ImageAdmin :: configureFormFields()调用时返回false,即使使用sonata_type_admin字段类型嵌入ImageAdmin也是如此。 I'm quite confused... 我很困惑......

Anyway, I hope it is possible to get hold of the object in some obvious way that I've overlooked and somebody here can help enlighten me! 无论如何,我希望有可能以一种我忽略的显而易见的方式抓住这个对象,这里有人可以帮助启发我!

Thanks to Tautrimas for some ideas, but I managed to figure out an answer to this: 感谢Tautrimas的一些想法,但我设法找到了答案:

In ImageAdmin set this: 在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)
    ;
}

I'll post this in the upcoming SonataAdmin cookbook soon! 我很快就会在即将推出的SonataAdmin烹饪书中发布这个!

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

caponica's solution is working only on oneToOne relations, am I right? caponica的解决方案只适用于oneOoOne关系,对吗? In my oneToMany case , this: $parent->$getter() returns a collection, and I don't know how to identify the current subject. 在我的oneToMany案例中,这个:$ parent - > $ getter()返回一个集合,我不知道如何识别当前主题。 I've found this bug report: https://github.com/sonata-project/SonataAdminBundle/issues/1568 , which contains a fix for this, but it is still open, so I hope they merge it soon:( 我发现了这个错误报告: https//github.com/sonata-project/SonataAdminBundle/issues/1568 ,其中包含一个修复程序,但它仍然是打开的,所以我希望他们很快合并:(

Edit 编辑

With some research there is a temporary fix for this: Fixed getting wrong subject in sonata_type_collection 通过一些研究,有一个临时的解决方法: 修复了sonata_type_collection中的错误主题

In short: 简而言之:

create a class and copypaste the content of this file: AdminType then add this to your services.yml, and change the class namespace to you new class namespace: 创建一个类并复制该文件的内容: AdminType然后将其添加到services.yml中,并将类命名空间更改为新的类命名空间:

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

It still has a bug though: 它仍然有一个bug:

also fix doesn't work when enabled cascade_validation in the parent docment and embedded form has errors 当在父文档和嵌入表单中启用cascade_validation有错误时,也修复不起作用

Can you try $this->getForm()->getViewData(); 你能试试$this->getForm()->getViewData(); within your ImageAdmin? 你的ImageAdmin? This should get you the correct child entity. 这应该会为您提供正确的子实体。

I tried all these solutions, but none proved to work. 我尝试了所有这些解决方案,但没有一个证明可行。
So, I worked to find a solution. 所以,我努力寻找解决方案。 My solution is based on caponica's solution, but work on oneToMany case. 我的解决方案基于caponica的解决方案,但是在oneToMany案例上工作。 Tha solution I found is a workaround, but works good. 我找到的解决方案是一种解决方法,但效果很好。
It's working using the session. 它正在使用会话。

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];
}

And you get the correct object in the admin by: 并且您通过以下方式获得管理员中的正确对象:

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

So, when the parent needs to show the list of child admins, each child admin will run this function and will update the session parameter. 因此,当父级需要显示子管理员列表时,每个子管理员都将运行此功能并更新会话参数。 When all the elements have been taken, the session parameter is deleted. 获取所有元素后,将删除会话参数。
This code is made for lists with only 2 elements, but can be updated for any number of elements. 此代码仅适用于包含2个元素的列表,但可以针对任意数量的元素进行更新。

Hope this helps somebody :) 希望这有助于某人:)

I had same problem and i am able to do this through "Custom Form Type Extension" for which documentation is given on the link " http://symfony.com/doc/current/cookbook/form/create_form_type_extension.html " . 我有同样的问题,我可以通过“自定义表单类型扩展”执行此操作,其文档在链接“ http://symfony.com/doc/current/cookbook/form/create_form_type_extension.html ”上给出。

It is the perfect solution .. 这是完美的解决方案..

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

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