使用 sonata admin 上传图片

Image upload with sonata admin

参见上面的编辑

我认为这个问题很容易解决,但我现在找不到任何明确的答案。我希望你能有一个想法。

我正在尝试使用 sonata admin 上传图片。

在我的实体中我有这个字段

/**
 * @ORM\Column(type="string", length=2000)
 * @Assert\File(mimeTypes={ "image/png", "image/jpeg" })
 */
private $image;

当我转到奏鸣曲管理表单视图时。上传文件按钮在那里,定义如下

$formMapper->add('image', FileType::class);

但是当我尝试发送表单时,出现了这个错误

The form's view data is expected to be an instance of class Symfony\Component\HttpFoundation\File\File, but is a(n) string. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) string to an instance of Symfony\Component\HttpFoundation\File\File.

我暗示这是由于学说字符串类型。但我认为学说没有 "File" 类型。

感谢您的帮助。

编辑:

考虑到评论中提供的link,这是新的错误

The current field image is not linked to an admin. Please create one for the target entity : ``

<?php

  namespace App\Entity;
  // src/Entity/Image.php

  class Image{
  const SERVER_PATH_TO_IMAGE_FOLDER = '/public/images';

  /**
   * Unmapped property to handle file uploads
   */
  private $file;

  /**
   * @param UploadedFile $file
   */
  public function setFile(UploadedFile $file = null)
  {
      $this->file = $file;
  }

  /**
   * @return UploadedFile
   */
  public function getFile()
  {
      return $this->file;
  }

  /**
   * Manages the copying of the file to the relevant place on the server
   */
  public function upload()
  {
      // the file property can be empty if the field is not required
      if (null === $this->getFile()) {
          return;
      }

     // we use the original file name here but you should
     // sanitize it at least to avoid any security issues

     // move takes the target directory and target filename as params
     $this->getFile()->move(
         self::SERVER_PATH_TO_IMAGE_FOLDER,
         $this->getFile()->getClientOriginalName()
     );

     // set the path property to the filename where you've saved the file
     $this->filename = $this->getFile()->getClientOriginalName();

     // clean up the file property as you won't need it anymore
     $this->setFile(null);
 }

 /**
  * Lifecycle callback to upload the file to the server.
  */
 public function lifecycleFileUpload()
 {
     $this->upload();
 }

 /**
  * Updates the hash value to force the preUpdate and postUpdate events to fire.
  */
 public function refreshUpdated()
 {
    $this->setUpdated(new \DateTime());
 }

 // ... the rest of your class lives under here, including the generated fields
 //     such as filename and updated
 }

在我的 ForumAdmin 中,现在我有

protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper->add('name', TextType::class);
    $formMapper->add('description', TextAreaType::class);
    $formMapper->add('weight', IntegerType::class);
    $formMapper->add('category', EntityType::class, [
        'class' => Category::class,
        'choice_label' => 'name',
    ]);
    $formMapper
        ->add('image', AdminType::class)
    ;
}

protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
    $datagridMapper->add('name');
    $datagridMapper->add('category');
}

protected function configureListFields(ListMapper $listMapper)
{
    $listMapper->addIdentifier('name');
    $listMapper->addIdentifier('description');
    $listMapper->addIdentifier('category');
    $listMapper->addIdentifier('weight');
    $listMapper->addIdentifier('createdAt');
    $listMapper->addIdentifier('updatedAt');
    $listMapper->addIdentifier('image');
}

public function prePersist($object)
{
    parent::prePersist($object);
    $this->manageEmbeddedImageAdmins($object);
    if($object instanceof Forum){
        $object->setCreatedAt(new \DateTime('now'));
        $object->setUpdatedAt(new \DateTime('now'));
        $object->setStatus("NO_NEW");
    }

}

public function preUpdate($page)
{
    $this->manageEmbeddedImageAdmins($page);
}

private function manageEmbeddedImageAdmins($page)
{
    // Cycle through each field
    foreach ($this->getFormFieldDescriptions() as $fieldName => $fieldDescription) {
        // detect embedded Admins that manage Images
        if ($fieldDescription->getType() === 'sonata_type_admin' &&
            ($associationMapping = $fieldDescription->getAssociationMapping()) &&
            $associationMapping['targetEntity'] === 'App\Entity\Image'
        ) {
            $getter = 'get'.$fieldName;
            $setter = 'set'.$fieldName;

            /** @var Image $image */
            $image = $page->$getter();

            if ($image) {
                if ($image->getFile()) {
                    // update the Image to trigger file management
                    $image->refreshUpdated();
                } elseif (!$image->getFile() && !$image->getFilename()) {
                    // prevent Sf/Sonata trying to create and persist an empty Image
                    $page->$setter(null);
                }
            }
        }
    }
}

我也有这个 ImageAdmin,即使我不明白它为什么有用

final class ImageAdmin extends AbstractAdmin{
protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper
        ->add('image', FileType::class);
}

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

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

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

// ...
}

The current field image is not linked to an admin. Please create one for the target entity : ``

要修复此错误,您需要像这样在文件 sonata_admin.yaml 中添加服务:

services:
...
   admin.image:
            class: App\Admin\ImageAdmin
            arguments: [~, App\Entity\File, ~]
            tags:
                - { name: sonata.admin, manager_type: orm, label: 'admin.image' }
            public: true