Symfony 4.4:entity/model 属性 为图像文件上传保留的更新由表单系统设置(结果始终为 null - 无错误)
Symfony 4.4: entity/model property reserved for the image file upload is newer being set by the form system (result is always null - no errors)
我正在尝试使用内部表单系统为基于 Symfony 4.4 的 API 服务实现输入数据过滤器。
在大多数情况下,它工作得很好 - 整数或基于文本的字段。当涉及 file/image 字段时,它以某种方式无法按预期工作。我尝试了官方文档中的各种集成选项,但没有成功。
由于遗留代码和提供的上传字段名称与确切实体之间的不一致,我准备了一个模型,而不是使用实体的模型,上传文件的数据将在之后实际存储:
<?php
namespace App\Model;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Validator\Constraints as Asserts;
class Avatar {
/**
* @var File
*
* @Asserts\Image()
* #Asserts\NotBlank() // Temporary disabled because this property never gets set due to the unknown reason.
*/
protected $file = null;
public function setFile(?File $file = null): self
{
$this->file = $file;
return $this;
}
public function getFile(): ?File
{
return $this->file;
}
}
表单类型如下所示:
<?php
namespace App\Form;
use App\Model\Avatar;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\Validator\Constraints;
class AvatarType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('file', Type\FileType::class, [
'label' => 'Image',
'required' => true,
'mapped' => true,
'constraints' => [
new Constraints\Image([
'maxSize' => '5M'
])
]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Avatar::class,
'csrf_protection' => false
]);
}
}
最后是控制器部分:
<?php
namespace App\Controller\Api;
use App\Controller\Api\BaseController;
use App\Entity\User;
use App\Model\Avatar;
use App\Form\AvatarType;
use App\Repository\UserRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
/**
* @Route("/me/avatar", name="app_api.me.avatar", methods={"POST"})
*/
class AvatarController extends BaseController
{
public function uploadAvatar(User $user, Request $request)
{
$avatar = new Avatar();
$form = $this->createForm(AvatarType::class, $avatar);
$form->submit($request->request->all());
if ($form->isSubmitted() && (!$form->isValid())) {
throw new \Exception((string) $form->getErrors(true));
}
dd($avatar->getFile());
...
}
}
当我尝试使用 PostMan 向此端点发出 POST 请求时,正文 -> 表单数据 -> 文件 属性 设置找到一些选定的图像文件,我总是得到 null 作为$avatar->getFile() 在控制器中的结果。
如果我使用 dd($form->getData()); 结果是相似的而不是 dd($avatar->getFile());
AvatarController.php on line 29:
App\Model\Avatar {#213795
#file: null
}
我试过使用 FormType 字段 属性 'mapped' => false 以及以下获取数据的方法,但结果是一样的 - 属性 'file' 永远不会设置,也不会报告错误。它适用于除 FileType 之外的所有其他字段类型(我已经测试过)。
dd($form['file']->getData()); // results in null
如果我添加具有其他类型(例如 TextType)的其他字段,它们将按预期工作:
AvatarController.php on line 29:
App\Model\Avatar {#213795
#file: null
#test: "some input text"
}
如果我使用来自输入请求的直接数据,它适用于文件 属性 但它是不安全的,并且没有 Symfony 功能提供的任何限制。
/** @var UploadedFile $ufile */
$ufile = $request->files->get('file');
dd($ufile);
=>
AvatarController.php on line 34:
Symfony\Component\HttpFoundation\File\UploadedFile {#528
-test: false
-originalName: "67922301_10219819530703883_7215519506519556096_n.jpg"
-mimeType: "image/jpeg"
-error: 0
path: "/tmp"
filename: "phpFHPPNL"
basename: "phpFHPPNL"
pathname: "/tmp/phpFHPPNL"
extension: ""
realPath: "/tmp/phpFHPPNL"
aTime: 2020-05-21 17:02:49
mTime: 2020-05-21 17:02:49
cTime: 2020-05-21 17:02:49
inode: 1451769
size: 145608
perms: 0100600
owner: 1000
group: 1000
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
}
我在这里做错了什么?有什么想法吗?
问题出在 $form->submit($request->request->all());
行。 $request->request
等同于 $_POST
,PHP 中的文件在 $_FILES
超全局中可用,可通过 $request->files
获得。无论如何,避免此类问题的最佳方法是调用 $form->handleRequest($request);
而不是手动提交数据。
我正在尝试使用内部表单系统为基于 Symfony 4.4 的 API 服务实现输入数据过滤器。
在大多数情况下,它工作得很好 - 整数或基于文本的字段。当涉及 file/image 字段时,它以某种方式无法按预期工作。我尝试了官方文档中的各种集成选项,但没有成功。
由于遗留代码和提供的上传字段名称与确切实体之间的不一致,我准备了一个模型,而不是使用实体的模型,上传文件的数据将在之后实际存储:
<?php
namespace App\Model;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Validator\Constraints as Asserts;
class Avatar {
/**
* @var File
*
* @Asserts\Image()
* #Asserts\NotBlank() // Temporary disabled because this property never gets set due to the unknown reason.
*/
protected $file = null;
public function setFile(?File $file = null): self
{
$this->file = $file;
return $this;
}
public function getFile(): ?File
{
return $this->file;
}
}
表单类型如下所示:
<?php
namespace App\Form;
use App\Model\Avatar;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\Validator\Constraints;
class AvatarType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('file', Type\FileType::class, [
'label' => 'Image',
'required' => true,
'mapped' => true,
'constraints' => [
new Constraints\Image([
'maxSize' => '5M'
])
]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Avatar::class,
'csrf_protection' => false
]);
}
}
最后是控制器部分:
<?php
namespace App\Controller\Api;
use App\Controller\Api\BaseController;
use App\Entity\User;
use App\Model\Avatar;
use App\Form\AvatarType;
use App\Repository\UserRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
/**
* @Route("/me/avatar", name="app_api.me.avatar", methods={"POST"})
*/
class AvatarController extends BaseController
{
public function uploadAvatar(User $user, Request $request)
{
$avatar = new Avatar();
$form = $this->createForm(AvatarType::class, $avatar);
$form->submit($request->request->all());
if ($form->isSubmitted() && (!$form->isValid())) {
throw new \Exception((string) $form->getErrors(true));
}
dd($avatar->getFile());
...
}
}
当我尝试使用 PostMan 向此端点发出 POST 请求时,正文 -> 表单数据 -> 文件 属性 设置找到一些选定的图像文件,我总是得到 null 作为$avatar->getFile() 在控制器中的结果。
如果我使用 dd($form->getData()); 结果是相似的而不是 dd($avatar->getFile());
AvatarController.php on line 29:
App\Model\Avatar {#213795
#file: null
}
我试过使用 FormType 字段 属性 'mapped' => false 以及以下获取数据的方法,但结果是一样的 - 属性 'file' 永远不会设置,也不会报告错误。它适用于除 FileType 之外的所有其他字段类型(我已经测试过)。
dd($form['file']->getData()); // results in null
如果我添加具有其他类型(例如 TextType)的其他字段,它们将按预期工作:
AvatarController.php on line 29:
App\Model\Avatar {#213795
#file: null
#test: "some input text"
}
如果我使用来自输入请求的直接数据,它适用于文件 属性 但它是不安全的,并且没有 Symfony 功能提供的任何限制。
/** @var UploadedFile $ufile */
$ufile = $request->files->get('file');
dd($ufile);
=>
AvatarController.php on line 34:
Symfony\Component\HttpFoundation\File\UploadedFile {#528
-test: false
-originalName: "67922301_10219819530703883_7215519506519556096_n.jpg"
-mimeType: "image/jpeg"
-error: 0
path: "/tmp"
filename: "phpFHPPNL"
basename: "phpFHPPNL"
pathname: "/tmp/phpFHPPNL"
extension: ""
realPath: "/tmp/phpFHPPNL"
aTime: 2020-05-21 17:02:49
mTime: 2020-05-21 17:02:49
cTime: 2020-05-21 17:02:49
inode: 1451769
size: 145608
perms: 0100600
owner: 1000
group: 1000
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
}
我在这里做错了什么?有什么想法吗?
问题出在 $form->submit($request->request->all());
行。 $request->request
等同于 $_POST
,PHP 中的文件在 $_FILES
超全局中可用,可通过 $request->files
获得。无论如何,避免此类问题的最佳方法是调用 $form->handleRequest($request);
而不是手动提交数据。