iphp/filestore-bundle

在 symfony 2 项目中上传 doctrine 实体的文件

v0.3.1 2016-10-05 08:04 UTC

This package is not auto-updated.

Last update: 2024-09-14 12:57:13 UTC


README

Build Status Total Downloads Code Climate

IphpFileStoreBundle 是一个用于自动化与实体关联的文件上传的 Symfony2 扩展包。该扩展包将根据每个属性指定的配置自动命名和保存上传的文件,使用配置和注解的混合方式。在实体创建并保存文件后,包含上传文件数据的数组将被保存到相应的属性中。该扩展包提供了不同的方式来命名上传的文件和目录。

有关俄语文档,请参阅 http://symfonydev.ru/iphpfilestorebundle/

安装

获取扩展包

在您的 composer.json 中添加以下行

{
    "require": {
        "iphp/filestore-bundle" : "@stable" 
    }
}

初始化扩展包

要开始使用扩展包,请将扩展包注册到您应用程序的内核类中

// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        // ...
         new Iphp\FileStoreBundle\IphpFileStoreBundle(),
    );
)

用法

IphpFileStoreBundle 尝试根据配置参数和注解的组合处理文件上传。为了使上传正常工作,您必须

  • 定义基本配置集
  • 注解实体

配置

# app/config/config.yml
iphp_file_store:
    mappings:
       photo:
           upload_dir:  %kernel.root_dir%/../web/photo
           upload_path: /photo

对于实体映射,upload_dirupload_path 是唯一必须的配置选项。

以下列出所有选项

  • upload_dir:上传文件到的目录
  • upload_path:上传目录的 Web 路径
  • namer:文件命名配置(参见下文“命名者”部分)
  • directory_namer:目录命名配置
  • delete_on_remove:如果要从文件系统中删除文件,则设置为 true
  • overwrite_duplicates:如果文件名相同,则设置为 true 以覆盖新文件。否则(默认情况),新文件名将添加额外的数字

注解实体

为了让您的实体与扩展包协同工作,您需要向其实体添加一些注解。首先,使用 Uploadable 注解注解您的类。这会让扩展包知道,当实体保存时,它应该在该类中查找要上传的文件,当实体加载时注入文件,并在实体删除时检查是否需要删除文件。接下来,您应该使用 UploadableField 注解注解当表单提交时包含 Symfony\Component\HttpFoundation\File\UploadedFile 实例的字段。以下是一些必需的 UploadableField 注解选项

  • mapping:在扩展包配置中指定的映射
  • fileDataProperty:存储文件数据的字段名

让我们看看使用一个虚构的 Photo ORM 实体的示例

推荐用法 - 在一个字段中上传(uploadPhoto),在另一个字段中存储文件数据(photo)

<?php

namespace Iphpsandbox\PhotoBundle\Entity;
use Iphp\FileStoreBundle\Mapping\Annotation as FileStore;
use Symfony\Component\Validator\Constraints as Assert;
 
/**
 * @FileStore\Uploadable
 */
class Photo
{
    /**
     * @var int
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    
   /**
     * @var array
     * @ORM\Column(type="array", nullable=true)
     */
    private $photoInfo;

    /**
     * @var File
     * @Assert\File( maxSize="20M")
     * @FileStore\UploadableField(mapping="photo", fileDataProperty ="photoInfo")
     */
    private $photoUpload;

    ...
     /* Getters and setters */
    ...
}

已弃用用法 - 在一个字段中上传和存储文件数据(photo)

<?php

namespace Iphpsandbox\PhotoBundle\Entity;
use Iphp\FileStoreBundle\Mapping\Annotation as FileStore;
use Symfony\Component\Validator\Constraints as Assert;
 
/**
 * @FileStore\Uploadable
 */
class Photo
{
    /**
     * @var int
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    
    /**
     * @var File
     * @Assert\File( maxSize="20M")
     * @FileStore\UploadableField(mapping="photo")
     * @ORM\Column(type="array", nullable=true)
     */
    private $photo;

    ...
     /* Getters and setters */
    ...
}

测试包中 Photo 实体的源代码

具有文件数据的字段必须具有类型为数组。

上传的文件数据

上传后注解字段包含包含以下元素的数组

  • path - Web 目录中文件的完整路径,包括上传目录的 Web 路径
  • size - 文件大小(字节)
  • fileName — 文件路径,相对于上传目录的网站路径
  • originalName — 上传前的原始文件名
  • mimeType — 文件MIME类型

如果上传的文件是图像,数组还将包含

  • width — 图像宽度
  • height — 图像高度

使用文件数据

要获取文件的路径,可以使用以下PHP代码

$photo = ... // load entity from db
$path = $photo->getPhoto()['path'];

或在Twig模板中

<img src="{{ photo.photo.path }}" alt="{{ photo.title}}" />

使用可上传实体的示例可以在控制器和上传模板中以及编辑模板中查看实体。

###上传照片列表的界面示例

interface with list of uploaded photos

使用表单字段类型

表单字段类型 Iphp\FileStoreBundle\Form\Type\FileType 可以在为 SonataAdminBundle 创建的admin类中使用。如果实体已经上传了文件,则会显示关于此文件的信息。此外,删除复选框允许删除上传的文件。

<?php

namespace Iphpsandbox\PhotoBundle\Admin;
 
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Iphp\FileStoreBundle\Form\Type\FileType as IphpFileType;
 
class PhotoAdmin extends Admin
{
    protected function configureListFields(ListMapper $listMapper)
    {
        return $listMapper->addIdentifier('title')
                          ->add ('date');
    }
 
    protected function configureFormFields(FormMapper $formMapper)
    {
        return $formMapper->add('title')
                         ->add ('date')
                         ->add('photo', IphpFileType::class);
    }
}

上传照片的sonata admin表单示例

Example of edit form for uploaded photo

自定义表单字段

例如,我们想显示原始上传图像的预览,以及使用LiipImagineBundle https://github.com/liip/LiipImagineBundle 生成的预览。要更改预览中的 <img src="..">,我们需要修改原始表单字段模板,该模板在 https://github.com/vitiko/IphpFileStoreBundle/blob/master/Resources/views/Form/fields.html.twig 中定义。

当在Twig中自定义表单字段块时,有两个选项可以确定自定义表单块的位置

方法1:表单主题化

自定义 iphp_file_widget 块的最简单方法是在实际渲染表单的模板中直接自定义它。

{% form_theme form _self %}

{% block iphp_file_widget_image_preview %}
     <div style="float: left" class="iphp_file_widget_image_preview">
        <a href="{{ fileUrl }}" target="_blank">
         <img src="{{ fileUrl | imagine_filter('photo_thumb') }}">
        </a>
     </div>

     <div>{{ file_data.width ~ 'x' ~ file_data.height }} </div>
{% endblock iphp_file_widget_image_preview %}

有关表单自定义的更多信息,请参阅https://symfony.ac.cn/doc/current/form/form_customization.html#form-theming

方法2:覆盖捆绑模板

要覆盖捆绑模板,只需将 vendor/iphp/filestore-bundle/Iphp/FileStoreBundle/Resources/views/Form/fields.html.twig 中的字段.html.twig 模板从 vendor/iphp/filestore-bundle/Iphp/FileStoreBundle 转到 app/Resources/IphpFileStoreBundle/views/Form/fields.html.twig(app/Resources/IphpFileStoreBundle 目录不存在,因此您需要创建它)。现在您可以自由地自定义模板。

例如,要显示所有表单中的预览

{#app/Resources/IphpFileStoreBundle/views/Form/fields.html.twig#}
{% extends 'IphpFileStoreBundle:Form:fields-base.html.twig' %}

{% block iphp_file_widget_image_preview %}
    <div style="float: left" class="iphp_file_widget_image_preview">
        <a href="{{ fileUrl }}" target="_blank">
         <img src="{{ fileUrl | imagine_filter('photo_thumb') }}">
        </a>
    </div>

    <div>{{ file_data.width ~ 'x' ~ file_data.height }} </div>
{% endblock iphp_file_widget_image_preview %}

有关覆盖第三方捆绑模板的更多信息,请参阅https://symfony.ac.cn/doc/current/templating/overriding.html

命名者

捆绑使用命名者来命名它保存到文件系统的文件和目录。如果没有为映射配置命名者,则捆绑将使用默认的转写命名者来命名上传的文件。如果您想更改此设置,则可以使用提供的命名者之一或实现一个自定义的命名者。

文件命名者

Translit

转写 - 将西里尔字母和其他字符替换为ASCII

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
           ...
           namer: ~ // default

要取消转写

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
           ...
           namer: false

使用实体字段值

文件名由实体字段值(字段名 - 标题)

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
          namer:
             property:
                params: { field : title }
             translit: ~

添加实体字段值

添加到实体字段值名称的开始(属性前缀)或结束(属性后缀)

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
          namer:
             translit: ~
             propertyPrefix:    #or propertyPostfix 
                   params: { field : id, delimiter: "_" }

使用实体字段名称

一个映射可以在多个字段中使用。字段名称可以用于命名文件

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
          namer:
             translit: ~
             propertyPostfix:
                  params: { use_field_name : true }

替换字符串

替换命名者的参数是键值对,包含搜索和替换字符串

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
          namer:
             translit: ~
             propertyPostfix:
                  params: { use_field_name : true }
             replace:
                 params: { File : ~ }

目录命名者

按日期创建子目录

例如:上传文件 123.jpg,实体的 createdAt 字段值 2013-01-01 - 文件路径将是 2013/01/123.jpg。深度选项 - 年、月、日。

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
         directory_namer:
             date:
                 params: { field : createdAt, depth : month }

使用实体字段值

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
         directory_namer:
             property:
                 params: { field : "id"}

使用实体字段名称

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
         directory_namer:
             property:
                params: { use_field_name : true }

使用实体类名称

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
         directory_namer:
             entityName: ~

使用目录命名者链

使用实体类名称和实体字段名称

# app/config/config.yml
iphp_file_store:
    mappings:
       some_entity:
         directory_namer:
             entityName: ~
             property:
                params: { use_field_name : true }