Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

chubbspet's avatar

Archiving Files using Spatie

Hi there

I am trying to create an archiving system for media files that are updated. My client requires files to be kept for 3 years. There seems to be very limited documentation around making copies of files. Here is one link that seems to be what I need:

https://spatie.be/docs/laravel-medialibrary/v10/advanced-usage/moving-media

The problem is, they don't say what the structure of the "$anotherModel" should be. I tried creating a model, based exactly from my media table, it is removing the files from media, but wont do the copy.

This is what I use for the copy section in my controller:

$medias = $enrolment->media;
      $media_archive = new MediaArchive();

      foreach($medias as $media)
      {
        $movedMediaItem = $media->move($media_archive, 'new-collection', 'local');
      }

and this is what my archive media model currently looks like:

<?php

namespace App\Models;

use DateTimeInterface;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;

class MediaArchive extends Model implements HasMedia
{
    use HasFactory;
    use InteractsWithMedia;

    public $table = 'media_archives';

    protected $dates = [
        'created_at',
        'updated_at',
        'deleted_at',
    ];

    protected $fillable = [
        'model_type',
        'model',
        'uuid',
        'collection_name',
        'name',
        'mime_type',
        'disk',
        'conversions_disk',
        'size',
        'manipulations',
        'custom_properties',
        'responsive_images',
        'order_column',
        'created_at',
        'updated_at',
        'deleted_at',
    ];

    protected function serializeDate(DateTimeInterface $date)
    {
        return $date->format('Y-m-d H:i:s');
    }

    public function move(HasMedia $model, $collectionName = 'default', string $diskName = ''): self
    {
        $newMedia = $this->copy($model, $collectionName, $diskName);

        $this->delete();

        return $newMedia;
    }

    public function copy(HasMedia $model, $collectionName = 'default', string $diskName = ''): self
    {
        $temporaryDirectory = TemporaryDirectory::create();

        $temporaryFile = $temporaryDirectory->path('/').DIRECTORY_SEPARATOR.$this->file_name;

        /** @var \Spatie\MediaLibrary\MediaCollections\Filesystem $filesystem */
        $filesystem = app(Filesystem::class);

        $filesystem->copyFromMediaLibrary($this, $temporaryFile);

        $newMedia = $model
            ->addMedia($temporaryFile)
            ->usingName($this->name)
            ->withCustomProperties($this->custom_properties)
            ->toMediaCollection($collectionName, $diskName);

        $temporaryDirectory->delete();

        return $newMedia;
    }
}

Any assistance will be appreciated.

0 likes
6 replies
LaryAI's avatar
Level 58

It looks like you are on the right track with the code you have provided. The $anotherModel in the Spatie documentation is referring to the model that you want to move the media to. In your case, it looks like you have created a MediaArchive model, so you should use that as the $anotherModel in the move method.

The move method also requires a collectionName and diskName parameter. The collectionName is the name of the collection that the media will be moved to, and the diskName is the name of the disk that the media will be stored on. You can find more information about these parameters in the Spatie documentation.

So, your code should look something like this:

$medias = $enrolment-&gt;media;
$media_archive = new MediaArchive();

foreach($medias as $media)
{
    $movedMediaItem = $media-&gt;move($media_archive, 'new-collection', 'local');
}

I hope this helps!

chubbspet's avatar

I am not sure if there is something missing in my archive model that is preventing the file from being written?

psrz's avatar

I don't quite understand your setup.

These files, you have them on some folder/storage and then after 3 years you need to move them to some other folder/storage ?

chubbspet's avatar

@psrz Thanks for your reply.

The archiving wont happen automatically. There is an ajax call that clear the worker's enrolment information. Part of this clearing is to remove all documents, but I want to archive them before removing. Hope that helps?

psrz's avatar

@chubbspet

$anotherModel can have any structure, can be any eloquent model, all you have to do is add the the interface/trait. In this case though maybe you can add a polimorphic relation to it so you know where the archived file comes from. Probably the only fields that this $anotherModel needs is the ones for the polimorphic relation

Also, the MediaArchive model doesn't need the move(), copy() methods, since it's the $media model (the eloquent model provided by the library) that performs these operations. Nor it needs any of the fields of the Media model.

Try to persist the MediaArchive model first, then you move the media to it.

To sum it up

       Schema::create('media_archive', function (Blueprint $table) {
            $table->id();
            $table->morphs('model');
            $table->timestamps();
        });

// MediaArchive.php

    public function model()
    {
        return $this->morphTo();
    }

Then in your controller:

$medias = $enrolment->media;

$media_archive = new MediaArchive();
$media_archive->model()->associate($enrolment);
$media_archive->save();

...
...

That should work

chubbspet's avatar

@psrz Thanks mate.

let me digest that and then try it. I will mark as correct as soon as it works, but what you are saying certainly looks correct.

Please or to participate in this conversation.