【问题标题】:Symfony2 base64 in Entity to File in Form (and inverse) using DataTransformer实体中的 Symfony2 base64 使用 DataTransformer 以形式(和反向)文件
【发布时间】:2015-04-06 11:15:34
【问题描述】:

我有一个博客平台,有一个实体 Category 这个实体与之关联

  • 一个名字
  • 一个图标(小 40*40 png)

由于文件非常小,mime 类型确保始终为 png,我决定将文件内容作为 Base64 编码字符串存储在实体/数据库中

这样页面可以立即呈现,而无需对非常小的文件进行额外的请求(对于 API 调用 GET /api/categories 也是如此)。对于预加载的数据,它工作得很好。当我想编辑一个类别时,问题就来了

我创建了一个带有图标文件类型的表单

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $transformer = new FileToBase64Transformer();

    $iconField = $builder->create('iconColor', 'file', ['required' => false]);
    $iconField->addModelTransformer($transformer);

    $builder
        ->add('title')
        ->add($iconField)
    ;
}

数据转换器是

class FileToBase64Transformer implements DataTransformerInterface
{
    public function transform($base64)
    {
        return null;
    }
    public function reverseTransform($file)
    {
        if (is_null($file)) {
            return null;
        }

        return base64_encode(file_get_contents($file));
    }
}

但是当我提交带有有效图像的表单时,表单失败 在分析器中,在表单部分我可以看到

Symfony\Component\Validator\ConstraintViolation Object(Symfony\Component\Form\Form).data.icon = THE_BASE_64_OF_THE_FILE

是因为数据在验证发生之前就被转换了吗?

  • 如何修改此代码以使其通过验证
  • 我需要考虑的是,如果用户没有上传新图像,当我编辑时会发生什么,如何保留图像?

【问题讨论】:

  • 为什么不将 BLOB 作为数据库字段?
  • @Paziツ 最初的想法是避免每次都重新转换为 base64(尤其是在一次更新发生之前 API 调用将被计算为数十万),但我目前正在考虑那条路
  • @Paziツ 实际上并没有改变很多东西,它只是删除了对 base64_encode 的调用,但是仍然需要进行转换(从 File 对象到“blob”)不是吗?
  • 我认为不需要 blob thete ^^ 我认为您应该在实体的 prePersist/preUpdate 事件中处理这个问题,就像在普通文件上传中一样
  • 这是一个长镜头,但也许使用 View Transformer 而不是 Model Transformer 会有所帮助...

标签: php forms validation symfony


【解决方案1】:

我目前的解决方案是在我的实体中为图标设置两个字段

/**
 * @Constraints\Image(
 *      maxWidth = 40,
 *      maxHeight = 40,
 *      allowSquare = true,
 *      mimeTypes = "image/png",
 * )
 */
private $iconFile = null;

/**
 * Base64 of the icon in color version
 *
 * @var string
 *
 * @ORM\Column(name="icon_color", type="text", nullable=true)
 */
private $icon = null;

(使用适当的 getter 和 setter)

然后将我的数据转换器用于整个类类别

class FileToBase64Transformer implements DataTransformerInterface
{
    /**
     * Transforms an object (file) to a base64.
     *
     * @param  $file
     * @return string
     */
    public function transform($channel)
    {
        return $channel;
    }

    /**
     * reverse transforms
     *
     */
    public function reverseTransform($categoryl)
    {
        $iconFile = $category->getIconFile();
        if (!is_null($iconFile)) {
            $channel->setIcon(
                base64_encode(file_get_contents($iconFile))
            );
        }
        return $channel;
    }
}

然后在我的 CategoryType 中将数据转换器关联到整个频道

/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $transformer = new FileToBase64Transformer();

    $builder
        ->add('title')
        ->add('theme_color')
        ->add('type')
        ->add('iconFile')
        ->addModelTransformer($transformer)
    ;
}

数据转换后验证仍然发生,但现在不再是问题,因为如果表单无效,实体将不会被持久化

【讨论】:

    猜你喜欢
    • 2015-10-22
    • 2014-09-24
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多