dia-nz / sortablefile
为 SilverStripe 4 添加到 UploadField 的排序功能的扩展。
Requires
- silverstripe/asset-admin: ^1.1
- silverstripe/assets: ^1.1
- silverstripe/config: ^1
- silverstripe/framework: ^4.1
Requires (Dev)
- phpunit/phpunit: ^5.7
README
为 SilverStripe 4.1+ 开发的扩展,允许通过 UploadField 上传的文件进行排序。
此模块装饰了现有的 UploadField 并为其添加了排序功能。这主要用于与文件或图像的 many_many 关系一起使用。
安装
此模块仅适用于 SilverStripe 4.1+。
对于与 SilverStripe 3 兼容的版本,请使用 1.x 版本。
最简单的方法是使用 composer
composer require dia-nz/sortablefile ^2.0
之后运行 dev/build。
用法
用法很简单。只需使用 SortableUploadField 代替 UploadField 来管理您的 many_many 关系。为了持久化排序顺序,需要向 many_many 关系添加一个额外的字段,该字段包含排序顺序。您可以通过指定 many_many_extraFields 中的排序列来实现(请参见下面的示例)。
默认情况下,SortableUploadField 假设排序列的名称为 SortOrder。如果您想使用其他字段名(例如 Sort),则必须明确设置它。
SortableUploadField::create('Files')->setSortColumn('Sort');
许多许多设置示例
假设我们有一个 PortfolioPage,该页面附带了多个 Images。
PortfolioPage 看起来像这样
use SilverStripe\Assets\Image; use SilverStripe\Forms\FieldList; use Bummzack\SortableFile\Forms\SortableUploadField; class PortfolioPage extends Page { // This page can have many images private static $many_many = [ 'Images' => Image::class ]; // this adds the SortOrder field to the relation table. // Please note that the key (in this case 'Images') // has to be the same key as in the $many_many definition! private static $many_many_extraFields = [ 'Images' => ['SortOrder' => 'Int'] ]; public function getCMSFields() { $this->beforeUpdateCMSFields(function (FieldList $fields) { $fields->addFieldToTab('Root.Main', SortableUploadField::create( 'Images', $this->fieldLabel('Images') )); }); return parent::getCMSFields(); } }
一旦按照上述方式设置,那么您应该能够在 CMS 中添加图像并通过拖拽来排序它们(使用左侧的句柄)。
模板
通过关系表对文件进行排序并不容易通过 DataExtension 实现。这就是为什么目前需要用户实现一个将返回排序文件的 getter,大致如下
// Use this in your templates to get the correctly sorted images public function SortedImages() { return $this->Images()->Sort('SortOrder'); }
然后在您的模板中使用
<% loop $SortedImages %>
$ScaleWidth(500)
<% end_loop %>
或者,您可以在模板中直接使用排序语句,这将在您的页面类中消除对特殊 getter 方法的需要。
<% loop $Images.Sort('SortOrder') %>
$ScaleWidth(500)
<% end_loop %>
许多许多通过
此模块还支持编辑许多许多通过列表。使用 many_many through 的优点是,您的关联可以正确地版本化。
设置示例
这是一个使用与上面相同的 PortfolioPage 的示例设置,但现在使用 many_many through。如果这看起来不清楚,请参阅官方文档。
首先,PortfolioPage 类
<?php use Bummzack\SortableFile\Forms\SortableUploadField; use SilverStripe\Forms\FieldList; class PortfolioPage extends Page { private static $many_many = [ 'Images' => [ 'through' => PortfolioImage::class, 'from' => 'PortfolioPage', 'to' => 'Image', ] ]; // This is required to automatically publish your images // whenever you publish your page private static $owns = [ 'Images' ]; // This is required to publish deletions as well, // as this will not happen by default! private static $cascade_deletes = [ 'Images' ]; public function getCMSFields() { $this->beforeUpdateCMSFields(function (FieldList $fields) { $fields->addFieldToTab('Root.Main', SortableUploadField::create( 'Images', $this->fieldLabel('Images') )); }); return parent::getCMSFields(); } // This is a helper method, that is needed to display the items in the // correct order. Is required for proper CMS functionality and can be // used in templates as $getImages public function getImages() { return $this->Images()->sort('SortOrder'); } }
many_many through 关系的思路是,您有一个连接对象的中介 DataObject。因此,我们添加一个名为 PortfolioImage 的 DataObject。
<?php use SilverStripe\Assets\Image; use SilverStripe\ORM\DataObject; use SilverStripe\Versioned\Versioned; class PortfolioImage extends DataObject { private static $db = [ 'SortOrder' => 'Int' ]; private static $has_one = [ 'Image' => Image::class, 'PortfolioPage' => PortfolioPage::class ]; private static $default_sort = 'SortOrder'; // It's important that you add the Versioned extension to this! private static $extensions = [ Versioned::class ]; }
我们还应该向 Image 类添加 belongs_many_many 关系。这通过配置非常容易完成。因此,在您的 mysite/_config/config.yml 中添加
SilverStripe\Assets\Image: belongs_many_many: PortfolioPages: PortfolioPage.Images
对 has_many 支持发生了什么变化?
由于如果文件只能添加到单个页面,可能会造成非常糟糕的用户体验,因此已取消对 has_many 关系的 support。想象一下,用户将图像添加到 Page A,然后通过 从文件添加 将相同的图像添加到 Page B。然后,该文件将从 Page A 中删除,没有任何警告或解释,这是很差的 UX。
