Поле изображения Sonata Admin

Я использую серверную часть Sonata Admin, и я хотел бы добавить новое поле изображения в свой пользовательский объект, который является аватаром. Так как я уже использую SonataMediaBundle Я следовал этому руководству: https://sonata-project.org/blog/2013/10/11/mediabundle-mediatype-improved

Вот моя конфигурация объекта:

/**
 * @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;

К сожалению у меня много проблем:

  1. В моем бэк-энде превью не показывается:
  2. Если я удаляю медиа в галерее, я получаю эту ошибку при редактировании пользователя: Entity of type 'Application\Sonata\MediaBundle\Entity\Media' for IDs id(6) was not found
  3. Результирующий API (сгенерированный с помощью FOSRestBundle) непригоден для клиента:
"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
    }

Большое спасибо.

1 ответ

Решение

Я решил все 3 проблемы! Я положил здесь свои решения для всех тех, кто имеет такие же трудности.

  1. В моем бэк-энде превью не показывается:

Как объяснено здесь, я должен добавить виджет формы config.yml файл:

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

И по моему UserAdmin:

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

Теперь превью будет показано:)

  1. Если я удаляю мультимедиа в галерее, я получаю эту ошибку при редактировании пользователя: не найден объект типа "Application\Sonata\MediaBundle\Entity\Media" для идентификаторов id(6)

Как объяснено здесь, мне нужно добавить onDelete="SET NULL" на моей сущности:

/**
 * @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. Результирующий API (сгенерированный с помощью FOSRestBundle) непригоден для клиента:

Это было очень сложно, но я смог реализовать собственный обработчик JMS, начиная с этого поста.

Я заглянул в SonataMediaBundle Исходный код, и я нашел этот фрагмент:

/**
 * 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;
}

Поэтому я включил его в свой источник, и полный обработчик выглядит следующим образом:

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

Сервисные настройки:

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

И это все!

Другие вопросы по тегам