File Deleted when ActiveRecord Deleted

I have a curious issue that when an ActiveRecord row is deleted, the image file whose path was stored in that row is also deleted.

I’m using oEmbed to validate a video url and retrieve the thumbnail. The thumbnail is saved to disk and a copy is made (imgA.png and imgA-original.png)

$thumbnailUrl = $this->getVideo('thumbnail');
$thumbnail = new Image($thumbnailUrl); // using Treinetic\ImageArtist
// crop and scale the thumbnail
// Save this image and later overlay a play button
$thumbnail->save($this->thumbnailBaseFilename . '.png', IMAGETYPE_PNG);
// Save the original image
copy($this->thumbnailBaseFilename . '.png', $this->thumbnailBaseFilename . '-original.png');
// Save path to db
$this->updateAttributes(['video_thumbnail' => $this->thumbnailFilename . '.png']);

Note that only the path for imgA.png is saved to db. Later on, if I delete the AR row with $block->delete(), imgA.png is also deleted, but imgA-original.png is left.

Another strange thing happens if I duplicate the AR row, copy both images to new filenames (e.g. imgB.png and imgB-original.png), and save the new filename (imgB.png) to the new row. Now if I delete this new AR row, the image from the first AR is deleted (imgA.png). The other three images are left (imgA-original.png, imgB.png, imgB-original.png).

public function duplicateBlock()
{
    // new block
    $block = $this->block;
    $blockAttr = $block->attributes;
    unset($blockAttr[$block->primaryKey()[0]]);
    $blockClassName = $block::className();
    $newBlock = new $blockClassName();
    $newBlock->save();
    $newBlock->updateAttributes($blockAttr);
     //
    $newBlock->duplicateVideoThumbnail($block->id);
}

public function duplicateVideoThumbnail($bid)
{
    $oldBlock = self::findOne($bid);
    $oldFilename = Yii::getAlias('@webroot') . self::UPLOAD_PATH . $oldBlock->hasBlock->id . '-' . $oldBlock->id;
    $newFilename = Yii::getAlias('@webroot') . self::UPLOAD_PATH . $this->hasBlock->id . '-' . $this->id;
    if (file_exists($oldFilename . '.png')) {
        copy($oldFilename . '.png', $newFilename . '.png');
    }
    if (file_exists($oldFilename . '-original.png')) {
        copy($oldFilename . '-original.png', $newFilename . '-original.png');
    }
}

I tried it with DAO and the file doesn’t get deleted. This is only happening with ActiveRecord.

Where are you actually deleting the file? Use php function unlink to delete the file

public function deleteVideoRow($bid)
{
    $model = YourARClass::findOne(['id'  => $bid]);
    if (@unlink($model->filepath)) {
        $model->delete();
        return $this->redirect(...);
    }
    //we failed to delete show error message
}

Thanks for your reply. I know about unlink. I delete the file with unlink before I delete the AR row. The problem is that the file is being deleted without unlink. I’ve worked around this issue now, but it would still be a problem if I wanted to keep the file.

Yii Active record does not know how to delete, so Either

  1. You are using custom AR class with some hidden stuffs in there
  2. You attached a behavior to the AR which is doing the deleting

If you can provide sample minima code, I can take a look of it!

I have a behavior attached to that attribute for manual upload. The problem happens without using the manual upload when the image is fetched via oEmbed, but the behavior must be affecting it. I should have thought of that!

'video_thumbnail' => [
    'class' => CutterBehavior::className(),
    'attributes' => ['video_thumbnail'],
    'baseDir' => self::UPLOAD_PATH,
    'basePath' => '@webroot',
    'hbid' => $this->hbid,
    'blockId' => $this->id,
],

Good that you solved it

1 Like

Thanks for your help!

1 Like