lch / media-bundle
Symfony LchMediaBundle
Requires
- php: ^7.2
- ext-imagick: *
- friendsofsymfony/jsrouting-bundle: ^2.3
- knplabs/doctrine-behaviors: ^2.0
- lch/components-bundle: ^1.2
- symfony/framework-bundle: ^4.4
- twig/extensions: 1.5.*
README
此包为Symfony 3提供了一种全面且代码密集的方式处理媒体。特性
- 在
config.yml
中定义 媒体类型 - 提供 事件 来挂钩所有流程(CRUD)
- 提供 表单类型 以便在管理界面中轻松交互(选择现有媒体/创建新媒体)
- 提供Twig扩展以简化在Twig文件中的媒体显示和操作(获取URL、缩略图...)
- 提供 验证器 以限制媒体范围(大小、分辨率等)
安装和先决条件
Imagick用于生成缩略图和图像大小集。在GUI方面,包使用 Bootstrap 4 和 jQuery。请确保满足这两个依赖项,尤其是在管理屏幕(媒体选择/创建)上
安装时,请使用: composer require lch/media-bundle
配置和使用
一般说明
默认情况下,MediaBundle定义了2种类型: 图像 和 pdf。您可以使用这些类型作为自定义类型的基类。
以下是显示的类型和可用的字段
媒体类型声明
您需要在 config.yml
中定义您的 媒体类型。您可以使用以下语法定义任意数量的类型
lch_media: types: image: name: 'your_project.image.name' # the translated name for front presentation entity: 'YourBundle\Entity\Media\Image' # the entity to be used form: 'YourBundle\Form\Media\ImageType' # the form to be used when adding media add_view: 'YourBundle/Media/Image/fragments:add.html.twig' # the add form view to be used when adding media thumbnail_view: 'YourBundle/Media/Resource/fragments:thumbnail.html.twig' # the view used for displaying thumbnail list_item_view: 'YourBundle/Media/Resource/fragments:list.item.html.twig' # the view used for displaying list item in selection lists extensions: ['jpg', 'jpeg', 'png', 'gif'] # allowed extensions max_items_per_page: 20 # not required, 20 per default thumbnail_sizes: news: width: 396 height: 227
让我们逐个复习每个给定键的示例
实体
上述声明图像的最小类可能是
<?php namespace YourBundle\Bundle\Entity\Media; use Doctrine\ORM\Mapping as ORM; use Knp\DoctrineBehaviors\Model\Blameable\Blameable; use Knp\DoctrineBehaviors\Model\Timestampable\Timestampable; use Lch\MediaBundle\Entity\Image as BaseImage; /** * Image * * @ORM\Table(name="image") * @ORM\Entity(repositoryClass="YourBundle\Repository\Media\ImageRepository") */ class Image extends BaseImage { use Blameable, Timestampable; }
它扩展了 Lch\MediaBundle\Entity\Image
。如果您想从头开始,您必须从 Media
扩展并使用 Storable
行为来触发与包中文件存储相关的所有操作。
表单
最小表单类可能是
<?php namespace YourBundle\Form\Media; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Lch\MediaBundle\Form\ImageType as BaseImageType; // Extends BaseImageType here for overriding constants class ImageType extends BaseImageType { /** * BaseImageType defines a NAME constant for generic image type. You override it here with your type name */ const NAME = 'your_image_type'; /** * Same for root translation path to be used in your particular type case */ const ROOT_TRANSLATION_PATH = 'your.back.media.form.image'; /** * @inheritdoc */ public function buildForm(FormBuilderInterface $builder, array $options) { // Explicit parent call is required for constant overriding parent::buildForm($builder, $options); } /** * @inheritdoc */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => 'YourBundle\Entity\Media\Image' ]); } /** * @inheritdoc */ public function getParent() { return BaseImageType::class; } }
添加视图
以下是为由包定义的通用Image定义的添加视图
{% form_theme mediaForm 'bootstrap_3_layout.html.twig' %} {{ form_errors(mediaForm) }} {{ form_start(mediaForm) }} {{ form_row(mediaForm.file) }} {{ form_row(mediaForm.name) }} {{ form_row(mediaForm.alt) }} <div class="text-right col-xs-12"> {{ form_row(mediaForm.submit) }} </div> {{ form_rest(mediaForm) }} {{ form_end(mediaForm) }}
如果您定义自己的,您必须使用 mediaForm
作为表单变量。
缩略图视图
以下是由包定义的通用Image的缩略图视图
<img src="{{ thumbnailEvent.thumbnailPath }}" alt="{{ thumbnailEvent.media.alt }}" />
注意:如 下面 所示,大多数逻辑都与 事件相关。缩略图生成就是这样的事情,因此访问缩略图数据通过事件对象进行
列表项视图
以下是由包定义的通用Image的列表项视图。您将在下面的 twig方法 中找到进一步说明
{% set attrs = "" %} {% for key, attr in attributes %} {% set attrs = attrs ~ " " ~ key ~ '=' ~ attr %} {% endfor %} {% set size = listItemEvent.media.file.getSize()/1000 %} <div {{ attrs }} class="{% if attributes.fullSize is defined and attributes.fullSize == true %}col-xs-12{% else %}col-xs-6 col-sm-4 col-md-3{% endif %} media" data-id="{{ listItemEvent.media.id }}" data-type="{{ getClass(listItemEvent.media) }}" data-url="{{ get_url(listItemEvent.media) }}" data-name="{{ listItemEvent.media.name }}" data-width="{{ listItemEvent.media.width }}" data-height="{{ listItemEvent.media.height }}" data-size="{{ size }}" > <div class="col-xs-4"> {{ get_thumbnail(listItemEvent.media) }} </div> <div class="col-xs-8"> <p>{{ listItemEvent.media.name }}</p> <p><strong>{{ listItemEvent.media.width }}</strong>px x <strong>{{ listItemEvent.media.height }}</strong>px</p> <p><strong>{{ size }} Ko</strong></p> </div> </div>
注意:如 下面 所示,大多数逻辑都与 事件相关。缩略图生成就是这样的事情,因此访问缩略图数据通过事件对象进行
扩展
在这里,您定义允许此媒体类型的扩展,作为一个数组。
缩略图大小
更多信息请参阅 专用部分
Twig扩展 & 工具
{{ get_list_item(media, attributes) }}
:显示列表项{{ get_thumbnail(media, attributes) }}
:显示媒体缩略图(在getListItem中调用){{ get_thumbnail_url(media, attributes) }}
: 仅返回缩略图URL(其中get_thumbnail
将返回HTML标签)
{{ get_url(media, attributes) }}
: 返回指定媒体的URL。默认为直接媒体URL,但您可以轻松地在下载事件上挂载以返回更复杂的内容(例如私人资源的下载器)
以下是对上述方法的图形渲染
事件
以下是对bundle抛出的完整事件列表(在 Lch\Media\LchMediaEvents
中列出)
LchMediaEvents::DOWNLOAD
: 在MediaController
生成响应以发送文件之前触发,但 之后 进行安全检查LchMediaEvents::LIST_ITEM
: 当调用Twig方法{{ getListItem(media, attributes) }}
时,由MediaManager
触发LchMediaEvents::PRE_DELETE
: 在MediaController
删除媒体之前触发LchMediaEvents::PRE_PERSIST
: 在MediaController
持久化媒体之前触发LchMediaEvents::PRE_SEARCH
: 在每次列表调用时由MediaManager
触发LchMediaEvents::POST_DELETE
: 在MediaController
删除媒体后触发LchMediaEvents::POST_PERSIST
: 在MediaController
持久化媒体后触发LchMediaEvents::POST_SEARCH
: 在每次列表调用时由MediaManager
触发LchMediaEvents::REVERSE_TRANSFORM
: 由AddOrChooseMediaType
表单类型使用LchMediaEvents::SEARCH_FORM
: 在列表调用时由MediaManager
触发,以获取特定输入类型以便将搜索表单上下文化为媒体类型LchMediaEvents::PRE_STORAGE
: 在MediaController
存储媒体文件之前触发LchMediaEvents::POST_STORAGE
: 在MediaController
存储媒体文件之后触发LchMediaEvents::THUMBNAIL
: 当调用Twig方法{{ getThumbnail(media, attributes) }}
时由MediaManager
触发LchMediaEvents::TRANSFORM
: 由AddOrChooseMediaType
表单类型使用LchMediaEvents::URL
: 在调用Twig方法{{ getUrl(media, attributes) }}
时由MediaManager
触发
表单类型
该bundle提供2种表单类型,以便简化媒体选择/创建。首先,请确保在您的admin twig文件中添加正确的表单主题文件,即 LchMediaBundle:form:fields.html.twig
AddOrChooseMediaType
以下是一个经典用法
$builder ->add('myImage', AddOrChooseMediaType::class, [ 'entity_reference' => Image::class, 'label' => static::ROOT_TRANSLATION_PATH . ".my_image.label", 'modal_title' => static::ROOT_TRANSLATION_PATH . '.my_image.modal.title', 'image_width' => 1499, 'image_height' => 415, 'required' => false, 'attr' => [ 'helper' => static::ROOT_TRANSLATION_PATH . '.my_image.helper' ] ]) ;
尽管它非常清楚,请注意 entity_reference
是您想要在这里链接的媒体类。关于验证,您可以传递
image_width
和image_height
以获得所需的 精确 图像大小min_image_width
、max_image_width
、min_image_height
、max_image_height
以设置图像大小边界min_media_weight
和max_media_weight
以设置媒体大小
查看 验证器部分 以获取更多详细信息。
然后,您必须注册一个Twig命名空间,并将bundle的 field.html.twig
添加为 form_theme
twig: #... paths: #... '%kernel.project_dir%/vendor/lch/media-bundle/Resources/views': LchMediaBundle form_themes: #... - 'bootstrap_4_layout.html.twig' - '@LchMediaBundle\form\fields.html.twig'
假设您已按上述方式添加了form_theme,则twig父表单类型变为
{% block css %} {{ parent() }} {# Media #} <link rel="stylesheet" href="{{ asset('bundles/lchmedia/css/media.css') }}" type="text/css" /> {% endblock css %} {% block your_content %} { form_start(form) }} {{ form_errors(form) }} {# ... #} {{ form_row(form.myImage) }} {# ... #} {% endblock your_content %} {% block scripts %} {{ parent() }} {# Routing : needed for interaction in the media popin #} <script src="{{ asset('bundles/fosjsrouting/js/router.js') }}"></script> <script src="{{ path('fos_js_routing_js', {'callback': 'fos.Router.setData'}) }}"></script> {# Medias #} <script src="{{ asset('bundles/lchmedia/js/isotope.js') }}"></script> <script src="{{ asset('bundles/lchmedia/js/jquery.media.js') }}"></script> <script src="{{ asset('bundles/lchmedia/js/media-search.js') }}"></script> {% endblock scripts %}
您必须添加这些3个javascript文件才能使一切正常工作。
- 列表使用 isotope 来实现优雅的项目展示
- 所有逻辑(列表/创建)都通过jQuery插件
jquery.media.js
处理 media-search.js
包含围绕搜索的JS逻辑(外部化以用于特定库页面)
结果(自定义样式后)
点击按钮后,会弹出包含媒体选择器的媒体弹出窗口,其中选择器限于您提供的(限于entity_reference
)
您也可以从这里添加媒体(限于您提供的entity_reference
,并使用您提供的form
和add_view
在config.yml
中为媒体类型设置)
注意:如您在LchMediaBundle:form:fields.html.twig
中看到的那样,我们给所有相关的HTML输入ID后缀了一个随机唯一数字,因此可以安全地在同一表单中允许使用多个媒体类型.
添加或选择多个媒体类型
此类型用于选择一组媒体。它只使AddOrChooseMediaType
可重复
$builder ->add('resources', AddOrChooseMultipleMediasType::class, [ 'label' => static::ROOT_TRANSLATION_PATH . '.public_documents.label', 'allow_add' => true, 'allow_delete' => true, 'prototype' => true, 'entry_type' => AddOrChooseMediaType::class, 'entry_options' => [ 'entity_reference' => Resource::class, 'label' => "your_project.test.label", 'modal_title' => static::ROOT_TRANSLATION_PATH . '.public_documents.document.modal.title', 'attr' => [ 'helper' => static::ROOT_TRANSLATION_PATH . '.public_documents.document.helper' ] ], 'attr' => array( 'class' => 'public-documents', 'helper' => static::ROOT_TRANSLATION_PATH . '.public_documents.helper', ), ]) ;
我们建议使用出色的Symfony collection插件轻松处理集合。我们还需要详细阐述JS部分,所以现在您必须在动态添加媒体按钮时重复执行随机数字更改。
以下示例与上述AddOrChooseMultipleMediasType
链接(使用symfony collection)
$('.public-documents').collection({ up: '<a href="#" class="btn btn-default"><i class="glyphicon glyphicon-chevron-up"></i></a>', down: '<a href="#" class="btn btn-default"><i class="glyphicon glyphicon-chevron-down"></i></a>', add: '<a href="#" class="btn btn-default"><i class="glyphicon glyphicon-plus"></i></a>', remove: '<a href="#" class="btn btn-default"><i class="glyphicon glyphicon-minus"></i></a>', duplicate: '<a href="#" class="btn btn-default"><i class="glyphicon glyphicon-duplicate"></i></a>', // Change the random number to ensure uniqueness after_add: function(collection, element) { var $mediaSelector = element.find('.media-selector-container'); // Renew random ID on just added media selector $mediaSelector.lchMedia('renewRandomId'); return true; } }) );
结果(自定义样式后)
验证器
您将在Lch\MediaBundle\Validator
中找到几个内置验证器
- HasAllowedFileExtension:基于配置的扩展检查
- Weight:最小/最大,精确重量
- 图像
- ImageSize:用于图像大小检查(宽度,高度,最小宽度,最小高度)
所有验证器都在类和属性级别上工作。因此,您需要一次在媒体类上定义它们
<?php namespace YourBundle\Entity\Media; use Doctrine\ORM\Mapping as ORM; use Knp\DoctrineBehaviors\Model\Blameable\Blameable; use Knp\DoctrineBehaviors\Model\Timestampable\Timestampable; use Lch\MediaBundle\Behavior\MediaTaggable; use Lch\MediaBundle\Behavior\Storable; use Lch\MediaBundle\Entity\Media; use Lch\MediaBundle\Validator\Constraints as MediaAsset; /** * Resource * * @ORM\Table(name="resource") * @ORM\Entity(repositoryClass="YourBundle\Repository\Media\ResourceRepository") * @MediaAsset\HasAllowedFileExtension() * @MediaAsset\MediaWeight() */ class Resource extends Media { // Remember to use the Storable to ensure physical file is correctly stored use Storable, ; }
存储策略
待办事项
图像大小
使用Imagick,该组件执行2件事
- 为所有图像生成缩略图
- 为PDF文件生成可查看的缩略图(列表项和预览器的缩略图)
使用正确的键(thumbnail_sizes
)在config.yml
中声明媒体类型,您可以生成所需的任何数量的缩略图。
注意:到目前为止,我们使用图像的更长维度,并将另一个维度调整为保持同质性变换。因此,生成的图像可能不是精确的良好分辨率。待完善...
实际用例
下载控制
- 声明媒体(参见以上)
- 注册监听器/订阅者到LchMediaEvents::STORAGE以更改您的媒体存储(例如:添加一个"/private/"子文件夹)
- 添加匹配的路由,强制Symfony处理请求
ipc_media_download: path: /uploads/resources/{id} defaults: { _controller: LchMediaBundle:Media:download, class: '%lch_media.types.resource.entity%' } methods: [ GET ]
- 添加一个投票者以限制服务
- 选项:注册监听器/订阅者到LchMediaEvents::DOWNLOAD以控制要提供的内容(添加水印...)
待办事项:待完善,包括详细的事件使用示例