简体   繁体   中英

Sonata Admin Image Field

I am using the Sonata Admin back-end and I would like to add a new image field to my user entity which is an avatar. Since I am already using the SonataMediaBundle I followed this tutorial: https://sonata-project.org/blog/2013/10/11/mediabundle-mediatype-improved

Here is my entity configuration:

/**
 * @var \Application\Sonata\MediaBundle\Entity\Media
 *
 * @ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"all"}, fetch="LAZY")
 * @ORM\JoinColumn(name="avatar_id", referencedColumnName="id")
 */
protected $avatar;

Unfortunately I have many problems:

  1. In my back-end the preview is not shown: 在此处输入图片说明
  2. If I delete the media in the gallery I receive this error when editing the user: Entity of type 'Application\\Sonata\\MediaBundle\\Entity\\Media' for IDs id(6) was not found
  3. The resulting API (generated with FOSRestBundle) is unusable by the client:
 "avatar": { "provider_metadata": { "filename": "Test.png" }, "name": "Test.png", "description": null, "enabled": false, "provider_name": "sonata.media.provider.image", "provider_status": 1, "provider_reference": "325564b03489a6473e7c9def01dc58bab611eccb.png", "width": 1430, "height": 321, "length": null, "copyright": null, "author_name": null, "context": "default", "cdn_is_flushable": null, "cdn_flush_at": null, "cdn_status": null, "updated_at": "2017-08-08T12:31:19+02:00", "created_at": "2017-08-08T12:31:19+02:00", "content_type": "image/png", "size": 24978, "id": 7 }

I resolved all the 3 problems! I put here my solutions for all those who have the same difficulties.

  1. In my back-end the preview is not shown:

As explained here I have to add a custom form widget to my config.yml file:

twig:
    # Sonata form themes
    form_themes:
        - 'SonataMediaBundle:Form:media_widgets.html.twig'

And in my UserAdmin :

->with('Profile')
    ->add('avatar', 'sonata_media_type', array(
        'provider' => 'sonata.media.provider.image',
        'context'  => 'default',
    ))
->end()

Now the preview will be shown :)

  1. If I delete the media in the gallery I receive this error when editing the user: Entity of type 'Application\\Sonata\\MediaBundle\\Entity\\Media' for IDs id(6) was not found

As explained here I need to add onDelete="SET NULL" on my entity:

/**
 * @var \Application\Sonata\MediaBundle\Entity\Media
 *
 * @ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"persist"}, fetch="LAZY")
 * @ORM\JoinColumn(name="avatar_id", referencedColumnName="id", onDelete="SET NULL")
 */
protected $avatar;
  1. The resulting API (generated with FOSRestBundle) is unusable by the client:

This one was very tricky but I was able to implement a custom JMS handler getting started from this post.

I peeked into the SonataMediaBundle source code and I found this snippet:

/**
 * Returns media urls for each format.
 *
 * @ApiDoc(
 *  requirements={
 *      {"name"="id", "dataType"="integer", "requirement"="\d+", "description"="media id"}
 *  },
 *  statusCodes={
 *      200="Returned when successful",
 *      404="Returned when media is not found"
 *  }
 * )
 *
 * @param $id
 *
 * @return array
 */
public function getMediumFormatsAction($id)
{
    $media = $this->getMedium($id);

    $formats = array(MediaProviderInterface::FORMAT_REFERENCE);
    $formats = array_merge($formats, array_keys($this->mediaPool->getFormatNamesByContext($media->getContext())));

    $provider = $this->mediaPool->getProvider($media->getProviderName());

    $properties = array();
    foreach ($formats as $format) {
        $properties[$format]['url'] = $provider->generatePublicUrl($media, $format);
        $properties[$format]['properties'] = $provider->getHelperProperties($media, $format);
    }

    return $properties;
}

So I included it into my source and the complete handler is the following:

<?php

namespace AppBundle\Serializer;

use Application\Sonata\MediaBundle\Entity\Media;
use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\JsonSerializationVisitor;
use Sonata\MediaBundle\Provider\MediaProviderInterface;

class MediaHandler implements SubscribingHandlerInterface
{
    private $mediaPool;

    public function __construct($mediaPool)
    {
        $this->mediaPool = $mediaPool;
    }

    public static function getSubscribingMethods()
    {
        return array(
            array(
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'format'    => 'json',
                'type'      => 'Application\Sonata\MediaBundle\Entity\Media',
                'method'    => 'serializeToJson',
            ),
        );
    }

    public function serializeToJson(JsonSerializationVisitor $visitor, Media $media, array $type, Context $context)
    {
        $formats = array(MediaProviderInterface::FORMAT_REFERENCE);
        $formats = array_merge($formats, array_keys($this->mediaPool->getFormatNamesByContext($media->getContext())));

        $provider = $this->mediaPool->getProvider($media->getProviderName());

        $properties = array();
        foreach ($formats as $format) {
            $properties[$format]['url']        = $provider->generatePublicUrl($media, $format);
            $properties[$format]['properties'] = $provider->getHelperProperties($media, $format);
        }

        return $properties;
    }
}

Service settings:

app.serializer.media:
    class: AppBundle\Serializer\MediaHandler
    arguments:
      - '@sonata.media.pool'
    tags:
        - { name: jms_serializer.subscribing_handler }

And that's all!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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