【问题标题】:Symfony 4 file upload with entity带有实体的 Symfony 4 文件上传
【发布时间】:2019-12-27 20:16:50
【问题描述】:

我正在开发我的模块,其中一部分是您可以向数据库添加新背景以在幻灯片中使用。

我有一个具有 3 个属性的 SlideshowBackground 实体:

/**
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @ORM\Column(type="string", length=150)
 */
private $image;

/**
 * @ORM\Column(type="string", length=100)
 */
private $imageAlt;

而且基本上,图片就是上传文件的字符串,包括相对路径。

我有以下SlideshowBackgroundType 作为添加幻灯片背景页面的表单:

class SlideshowBackgroundType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('image', FileType::class, [
            'required' => true
        ]);
        $builder->add('imageAlt', TextType::class, ['required' => true]);
    }
}

但是,如果我提交表单并检查$form->getData(),它包含以下数据:

SlideshowBackground {#419 ▼
-id: null
-image: "C:\wamp64\tmp\php5B96.tmp"
-imageAlt: "ty"
}

但是,这样我无法获取原始上传的文件名。我在控制器中使用以下代码:

$slideshowBackground = new SlideshowBackground();
$form = $this->createForm(SlideshowBackgroundType::class, $slideshowBackground);
$form->handleRequest($request);

如何使用SlideshowBackground 实体,同时还能上传未直接映射到image 的文件?

我尝试将我的 image 字段修改为以下内容:

$builder->add('image', FileType::class, [
    'required' => false,
    'mapped' => false
]);

然后我从$form->getData() 得到相同的结果,但是image 列为空。

另外,当我尝试使用最后一个代码提交时,image 上出现以下错误:

This value should not be null.

我知道SlideshowBackground 中的image 属性是必需的,而且应该是,但它不起作用,因为使用mapped => false 提交时未定义image。有什么办法可以解决这个问题?

【问题讨论】:

  • 查看docs example中的控制器代码。请务必过滤 getClientOriginalName() 的结果,因为它可能是攻击媒介。
  • @Cerad 我确实看过那里,但我还是无法弄清楚,因为它会带来额外的问题。我的表单使用我的实体,它有一个属性image,这是必需的,并且由于提交时它为空,它会引发错误。但是,AFAIK 应该需要 image,因为背景需要指定图像。
  • 没关系,我发现我的愚蠢,我得到了正确的数据,我发现了问题。还是谢谢
  • 是否与未设置映射为false有关?只是好奇。
  • 其实行不通。我将表单生成器中的image 输入更改为imageupload,它确实添加了一个新的未映射输入类型。但是,我的表单不起作用,因为 SlideshowBackground 实体中的 image 为 null,这是不可能发生的。因此,$form->isSubmitted() && $form->isValid() 将返回 false。我只检测到我在查看 $form->getData 并且只返回实体(而不是额外的字段)。所以我可以从表单中获取上传的图片,但我无法提交表单

标签: forms symfony file-upload symfony4


【解决方案1】:

我认为 OP 仍有问题,但不确定。无论如何,这是可行的:

class SlideshowBackgroundType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('image', FileType::class, [
            'required' => true,
            'mapped' => false, // *** NEED THIS ***
        ]);
        $builder->add('imageAlt', TextType::class, ['required' => true]);
        $builder->add('upload', SubmitType::class);
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => SlideshowBackground::class,
        ]);
    }
...
class IndexController extends AbstractController
{
    /** @Route("/upload", name="upload") */
    public function upload(Request $request)
    {
        $slideshowBackground = new SlideshowBackground();
        $form = $this->createForm(SlideshowBackgroundType::class, $slideshowBackground);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {

            /** @var UploadedFile $imageFile */
            $imageFile = $form['image']->getData();
            dump($imageFile);

            // It is up to you to get the original filename per the example in the docs
            $originalFilename = pathinfo($imageFile->getClientOriginalName(), PATHINFO_FILENAME);
            // this is needed to safely include the file name as part of the URL
            //$safeFilename = transliterator_transliterate('Any-Latin; Latin-ASCII; [^A-Za-z0-9_] remove; Lower()', $originalFilename);
            //$newFilename = $safeFilename.'-'.uniqid().'.'.$brochureFile->guessExtension();

            $slideshowBackground->setImage($originalFilename); // *** NEED THIS ***
            dump($slideshowBackground);
            ...
        }

由 OP 编辑​​:

这个答案是正确的,但是,为了将来参考/其他人,请注意,如果在config/packages/validator.yaml 中未注释以下代码,这将不起作用

auto_mapping:
            App\Entity\: []

因此,如果此代码不起作用,请检查 auto_mapping 代码是否被注释掉。

回答者编辑:​​

我允许上述编辑,因为它显然解决了问题。但是,我无法重现该问题。很确定在 $form->handleRequest 和 $form->isValid 之间执行了更多代码。

【讨论】:

  • 这会在image 上传字段上给出错误This value should not be null.。这意味着$form->isSubmitted() && $form->isValid() 也是错误的。这很可能是因为imageSlideshowBackground 实体中的一个属性,它是必需但未设置的。
  • @JoshuaBakker 你还有其他事情要做。我在发布之前测试了代码,它按预期工作。映射属性足够聪明,可以让属性通过“不为空”测试。这是我的工作代码的 github 存储库:github.com/cerad/upload
  • 我看到您的 SlideshowBackground 不是数据库实体类。也许这就是问题所在。我才意识到我从来没有说过它是一个数据库实体类。
  • 基本上是这样。我只是从未添加注释。表单组件不关心教义注释。如果您在某个地方(可能是表单侦听器或其他东西)进行了一些额外的验证,那么这可能会导致问题。
  • 不是真的,我已经使用我的表单类型类(从 AbstractType 扩展)创建了表单,并且我在 createform 中使用了实体类构造函数作为数据。而且我确实收到了错误,并且我没有使用任何其他可能破坏它的 AFAIK。
猜你喜欢
  • 1970-01-01
  • 2019-02-11
  • 1970-01-01
  • 1970-01-01
  • 2019-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
相关资源
最近更新 更多