使用 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
参见上面的编辑
我认为这个问题很容易解决,但我现在找不到任何明确的答案。我希望你能有一个想法。
我正在尝试使用 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