【问题标题】:How to delete file (image) from filesystem when it is detached from DataObject in SilverStripe admin?如何从文件系统中删除文件(图像)从 SilverStripe 管理员中的 DataObject 分离?
【发布时间】:2018-07-22 00:19:48
【问题描述】:

例如我有这个代码

class MyDataObject extends DataObject {
    private static $has_one = [
        "MyImage" => Image::class,
    ];
    public function getCMSFields(){ 
        $fields = parent::getCMSFields();
        $fields->addFieldsToTab('Root.Main', [
            UploadField::create('MyImage');
        ]);
        return $fields;
    }
}

当用户在管理员中从 MyDataObject 中删除文件时

此文件仍保留在 cms 的“文件”部分、数据库和文件系统中,因此用户需要转到“文件”并手动删除。

在练习中,他经常在将文件从某个数据对象中分离后忘记删除文件,而所有这些文件都占据了很多位置。

当用户点击屏幕截图上的十字时,SilverStripe 如何自动从文件系统中删除文件?

【问题讨论】:

    标签: forms orm silverstripe


    【解决方案1】:

    您的数据对象需要onAfterDelete()。在那里你可以删除文件。 (不要忘记在你的方法中调用Parent::onAfterDelete()

    ** 更新 **

    或者,如果仅当用户编辑而不是删除您的对象时,那么onAfterWrite() 是您的朋友。在那里你可以比较图像的新旧ID,如果不同,删除旧ID的图像。

    【讨论】:

    • 不要忘记检查文件是否在其他地方使用;例如如果它是您自己的 DataObject 的 has_many
    • @Ben 您是否正确理解了这个问题?我不知道。您正在谈论级联删除,但有问题的 MyDataObject 实例需要保留。从 MyDataObject 实例中仅删除图像。现在我正在研究onAfterWrite()$this->getChangedFields()
    • @FlamyTwista 这不是 cascadeDelete,而只是一个钩子,当用户删除您的数据对象时,您可以在其中删除(或执行任何操作)您的相关对象。 “有问题的 MyDataObject 实例需要保留”=>这不是您在问题中所说的。 “当用户在管理员中从 MyDataObject 中删除文件时。此文件仍保留在 cms 的“文件”部分、数据库和文件系统中,因此用户需要转到“文件”并手动删除。SilverStripe 如何自动从文件系统中删除文件当用户点击屏幕截图上的十字时?”听起来这正是您要问的。
    • @FlamyTwista 更新了编辑数据对象的响应
    【解决方案2】:

    为了解决这个问题我创建了这个扩展

    <?php
    use SilverStripe\ORM\DataExtension;
    use SilverStripe\Assets\File;
    
     class DataObjectRemoveImagesExt extends DataExtension {
    
         private function killFile($fileId) {
             $fileToRemove = File::get()->byId($fileId);
             if ($fileToRemove) $fileToRemove->delete();
         }
    
         public function onAfterWrite() {
             $changedFieldsArr = $this->owner->getChangedFields();
    
             if (!$this->owner->config()->get('kill_on_detach')) return;
    
             $detachList = $this->owner->config()->get('kill_on_detach');
    
             foreach ($detachList as $fileFieldName) {
                 if (!isset($changedFieldsArr["{$fileFieldName}ID"])) continue;
    
                 $changedFieldValues = $changedFieldsArr["{$fileFieldName}ID"];
    
                 if (
                     (
                         $changedFieldValues['before'] != $changedFieldValues['after']
                         &&
                         $changedFieldValues['before'] != 0
                         &&
                         $changedFieldValues['after'] != 0
                     )
                     ||
                     (
                         $changedFieldValues['after'] == 0
                         &&
                         $changedFieldValues['before'] != 0
                     )
                 ){
                     $this->killFile($changedFieldValues['before']);
                 }
             }
         }
     }
    

    用法:
    1. 附加到数据对象

    SilverStripe\ORM\DataObject:
      extensions:
        - DataObjectRemoveImagesExt
    
    1. 在您的自定义 DataObject 子对象中,使用此属性设置要删除的文件/图像

      私有静态 $kill_on_detach = [ '图片', '拇指', ];

    解决方案并不完美:

    • 即使文件附加到另一个 DataObject 实例,它也会杀死文件
    • 如果用户从管理面板分离文件并忘记,它不会杀死文件 保存数据对象

    如果有人想提出更好的决定 - 欢迎。

    【讨论】:

      猜你喜欢
      • 2018-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-25
      • 2015-12-03
      • 2021-01-29
      相关资源
      最近更新 更多