Forms 在SilverStripe admin中,当文件系统与DataObject分离时,如何从文件系统中删除文件(映像)?

Forms 在SilverStripe admin中,当文件系统与DataObject分离时,如何从文件系统中删除文件(映像)?,forms,orm,silverstripe,Forms,Orm,Silverstripe,例如,我有这个代码 class MyDataObject extends DataObject { private static $has_one = [ "MyImage" => Image::class, ]; public function getCMSFields(){ $fields = parent::getCMSFields(); $fields->addFieldsToTab('Root.Mai

例如,我有这个代码

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;
    }
}
当用户在admin中从MyDataObject中删除文件时

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

在实践中,他经常忘记在将文件从某个数据对象中分离出来后将其删除,而所有这些文件占据了很多位置


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

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

**更新**


或者,如果只有当用户正在编辑而不是删除您的对象时,
onAfterWrite()
才是您的朋友。在那里,您可以比较图像的旧ID和新ID,如果不同,请删除具有旧ID的图像。

要解决我创建此扩展的问题,请

<?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']);
             }
         }
     }
 }
  • 在自定义DataObject子对象中,使用此属性设置要删除的文件/图像

    私有静态$kill_on_detach=[ “图像”, “拇指”, ];

  • 解决方案并不完美:

    • 即使文件附加到另一个DataObject实例,它也会终止该文件
    • 若用户将文件从管理面板中分离并忘记,它不会终止文件 保存数据对象的步骤

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

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