在sonata管理包中管理一个到多个实体

时间:2014-12-27 13:55:51

标签: symfony sonata-admin


想象一下,您正在使用symfony2开发一个网站,它的管理面板使用Sonata Admin Bundle,当然想象您有一个名为Product的类,它拥有一些Images。 Image也是一个类,您在Product中设置了一对多关系到Image类。因此,每个图像都归产品所有,因此您需要在Product Admin类中管理Image Admin。
所以你应该面对一些问题。你能告诉我怎么样?
1.删​​除产品对象时,将删除与该产品相关的所有图像 2.当您在展示产品页面或添加新产品页面时,所有图像的图片显示在页面上。
(有没有使用奏鸣曲媒体包的解决方案吗?)
感谢

我使用Document类处理图片上传:

FstQst\WebBundle\Entity\Document:
    type: entity
    table: null
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO

    fields:
        updated:        # changed when files are uploaded, to force preUpdate and postUpdate to fire
            type:         datetime
            nullable:     true

        format:
            type: string
            length: 25
            nullable: true


    lifecycleCallbacks:
        prePersist:   [ preUpload ]
        preUpdate:    [ preUpload ]
        postPersist:  [upload]
        postUpdate:   [upload]
        postRemove: [removeUpload]

我有另一个类使用Document为图像添加一些功能:

FstQst\WebBundle\Entity\Post:
    type: entity
    table: null
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO

    fields:
        title:
            type: string
            length: 100
            nullable: true


    oneToOne:
        document:
            targetEntity: Document
            joinColumn:
                name: document_id
                referencedColumnName: id
            orphanRemoval: true

    manyToOne:
        site:
            targetEntity: VisitablePoint
            inversedBy: posts
            joinColumn:
                name: vPoint_id
                referencedColumnName: id

    lifecycleCallbacks: {  }

一个名为VisitablePoint的类,它使用Post类:

FstQst\WebBundle\Entity\VisitablePoint:
    type: entity
    table: visitablePoint
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO


    oneToMany:
        posts:
            targetEntity: Post
            mappedBy: site
            orphanRemoval: true

    lifecycleCallbacks: {  }

我将我的班级名称从Post更改为Image,并将VisitablePoint从我的旧帖子更改为Product。现在我想要访问VisitablePoint管理员/显示页面时,我会看到Post对象的图片而不是他们的标题。当然还有管理/编辑页面。
这些是管理员类:

<?php

namespace FstQst\WebBundle\Admin;

use FstQst\WebBundle\Entity\Document;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;

class DocumentAdmin extends Admin
{
    /**
     * @param ListMapper $listMapper
     */
    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper
            ->add('id')
            ->add('updated')
            ->add('_action', 'actions', array(
                'actions' => array(
                    'show' => array(),
                    'edit' => array(),
                    'delete' => array(),
                )
            ))
        ;
    }

    /**
     * @param FormMapper $formMapper
     */
    protected function configureFormFields(FormMapper $formMapper)
    {

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


    /**
     * @param ShowMapper $showMapper
     */
    protected function configureShowFields(ShowMapper $showMapper)
    {
        $showMapper
            ->add('id')
            ->add('updated')
            ->add('format')
        ;
    }

    public function prePersist($image) {
        $this->manageFileUpload($image);
    }

    public function preUpdate($image) {
        $this->manageFileUpload($image);
    }

    protected function manageFileUpload(Document $image) {
        if ($image->getFile()) {
            $image->refreshUpdated();
        }
    }

    protected function getFieldOptionForImagePreview($maxSize = 200){
        if($this->hasParentFieldDescription()) { // this Admin is embedded
            // $getter will be something like 'getlogoImage'
            $getter = 'get' . $this->getParentFieldDescription()->getFieldName();

            // get hold of the parent object
            $parent = $this->getParentFieldDescription()->getAdmin()->getSubject();
            if ($parent) {
                $document = $parent->$getter();
            } else {
                $document = null;
            }
        } else {
            $document = $this->getSubject();
        }

        // use $fileFieldOptions so we can add other options to the field
        $fileFieldOptions = array('required' => false);
        if ($document && ($webPath = $document->getWebPath())) {
            // get the container so the full path to the image can be set
            $container = $this->getConfigurationPool()->getContainer();
            $fullPath = $container->get('request')->getBasePath().'/'.$webPath;
            //$fileFieldOptions['help'] = '<img src="/uploads/documents/10.png" class="admin-preview" style="max-height: 200px; max-width: 200px"/>';
            $fileFieldOptions['help'] = <<<START
<img src="$fullPath" style="max-height: {$maxSize}px; max-width: {$maxSize}px"/>
START;
        }

        return $fileFieldOptions;
    }

}

<?php

namespace FstQst\WebBundle\Admin;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;

class VisitablePointAdmin extends Admin
{

    /**
     * @param FormMapper $formMapper
     */
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->add('posts', 'sonata_type_model', array('multiple' => true, 'property' => 'title', 'label' => 'Image', 'required' => false))
        ;
    }

    /**
     * @param ShowMapper $showMapper
     */
    protected function configureShowFields(ShowMapper $showMapper)
    {
        $showMapper
             ->add('posts', 'sonata_type_collection', ['label' => 'Images',
                'required' => false, 'cascade_validation' => true,
                'by_reference' => false], ['edit' => 'inline', 'inline' => 'table'])
            ->end()
        ;
    }
}

1 个答案:

答案 0 :(得分:6)

一对多关系

<强> 1。删除产品对象时,将删除与该产品相关的所有图像。

您可以使用orphanRemoval =“true”

轻松管理此类删除
<?php
class Product{
    [...]
    /**
     * @ORM\OneToMany(targetEntity="Event", mappedBy="day", orphanRemoval="true", cascade={"all"})
     */
    private $images;
    [...]
}

在yml中,配置如下:

oneToMany:
  images:
    targetEntity: Image
    orphanRemoval: true
    mappedBy: product

<强> 2。当您在展示产品页面或添加新产品页面时,所有图像的图片都会显示在页面上。

您必须在configureFormFields中使用sonata_type_collection或使用ProductAdmin类的configureShowFields方法:

<?php
class ProductAdmin{
    [...]
    protected function configureFormFields(FormMapper $formMapper) {
        $formMapper
            ->with('tab_images')
                ->add('images', 'sonata_type_collection', array(
                    'required' => false,
                    'cascade_validation' => true,
                    'by_reference' => false,
                ), array(
                    'edit' => 'inline',
                    'inline' => 'table',
                ))
            ->end()
        ;
    }
    [...]
}

然后为ImageAdmin提供上传文件所需的一切。 您可能需要更改设置,因为我从个人项目中取出它,我不知道它是否完全适合您的需求。

在Sonata中显示图像

首先按如下方式配置ImageAdmin:

class ImageAdmin extends Admin
{
    [...]
    protected function configureShowFields(ShowMapper $showMapper) {
        $showMapper
            ->add('myImageAttr', 'image', array(
                'prefix' => '/',
            ))
        ;
    }
    [...]
    protected function configureListFields(ListMapper $listMapper) {
        $listMapper
            ->add('myImageAttr', 'image', array(
                'prefix' => '/',
                'width' => 100
            ))
        ;
    }
}

然后为list_image和show_image类型创建模板:

资源/视图/ CRUD / show_image.html.twig

{% extends 'SonataAdminBundle:CRUD:base_show_field.html.twig' %}
{% block field %}
    {% if value %}
        <img src="{% if field_description.options.prefix %}{{ field_description.options.prefix }}{% endif %}{{ value }}" />
    {% endif %}
{% endblock %}

资源/视图/ CRUD / list_image.html.twig

{% extends admin.getTemplate('base_list_field') %}

{% block field%}
{% spaceless %}
    {% set width = field_description.options.width is defined ? field_description.options.width : 50 %}
    {% set height = field_description.options.height is defined ? field_description.options.height : 50 %}
    {% if value %}
        <img src="{% if field_description.options.prefix is defined %}{{ field_description.options.prefix }}{% endif %}{{ value }}" 
            style="max-width:{{ width }}px; max-height:{{ height }}px;" />
    {% else %}
        <div class="no-image" style="width:{{ width }}px; height:{{ height }}px;"></div>
    {% endif %}
{% endspaceless %}
{% endblock %}

最后,将此配置添加到app / config / config.yml

sonata_doctrine_orm_admin:
  templates:
    types:
      show:
        image: YourBundle:CRUD:show_image.html.twig
      list:
        image: YourBundle:CRUD:list_image.html.twig

http://sonata-project.org/bundles/doctrine-orm-admin/master/doc/reference/templates.html