Skip to content

Importing ​

media-library:import copies existing files into the library. It reads three kinds of source: media managed by Spatie's laravel-medialibrary, rows from Awcodes Curator, and any folder on a disk.

bash
php artisan media-library:import spatie --model="App\Models\Product" --collection=images --folder=Products

php artisan media-library:import curator --update=posts.featured_image_id --update=pages.hero_id --map=storage/curator-map.json

php artisan media-library:import directory uploads/legacy --disk=public --folder=Legacy

Every file goes through the same pipeline as a normal upload: type and size checks, SVG sanitising, conversions, the MediaItemUploaded event and, if enabled, queued alt text. Files that fail a check are skipped with a warning, and the rest continue.

Options ​

OptionApplies toMeaning
sourceallspatie, curator or directory.
pathdirectoryFolder to import, relative to the disk root.
--disk=directoryDisk to read from. Defaults to the library disk.
--model=*spatieOnly media attached to these model classes. Repeat for several.
--collection=*spatieOnly these Spatie collections. Repeat for several.
--movespatieDelete the original Spatie media after it is copied.
--table=curatorTable holding the Curator rows. Defaults to curator.
--update=*curatorA table.column whose values are rewritten to the new ids. Repeat for several.
--folder=allPut everything into this folder, created when missing.
--map=allWrite a JSON map of old id to new library id to this file.
--tenant=allTenant key to assign to the imported records.
--tenant-model=allTenant model class. Required with --tenant.
--dry-runallCount what would be imported and write nothing.

Spatie media ​

bash
php artisan media-library:import spatie

This copies every Spatie media row that does not already belong to the library, then attaches the new library item back to the model that owned it, in the same collection. Usage tracking works straight away, and $product->getMediaLibraryItems('images') returns the files once the model uses HasMediaLibrary.

  • The item name comes from the media name. alt and caption are read from the media's custom properties.
  • Without --folder, files go into Imported/<ModelName>, for example Imported/Product.
  • The originals stay in place unless you pass --move, which deletes each Spatie media row and its file after it was copied.

Curator ​

bash
php artisan media-library:import curator --update=posts.featured_image_id

This reads the curator table (change it with --table) and copies each file from its disk and path. Title, alt text, caption and description come across when the row has them. Without --folder, files go into Imported/Curator.

--update=table.column rewrites every value in that column from the old Curator id to the new library id, in one query per 500 ids. Pass it once for each column that stores a Curator id. A column that does not exist is skipped with a warning.

WARNING

--update replaces values by looking up old ids. If you run it a second time, values that were already rewritten can match an old id and be changed again. Back up the database first and run the rewrite once. Rows whose file failed to import keep their old id.

Directory ​

bash
php artisan media-library:import directory uploads/legacy --disk=public --folder=Legacy

This imports every file under the path. Sub directories become folders, nested under --folder when you give one. Files starting with a dot are ignored. Files are copied, so the originals are left alone.

Dry runs ​

bash
php artisan media-library:import spatie --dry-run -v

A dry run creates no files, no folders and no map file. It prints Would import N files, skipped M. Add -v to list each file. Already imported files count as skipped.

Safe to run again ​

Each imported item records where it came from in its custom properties (imported_from, such as spatie:12, curator:100 or directory:public:uploads/legacy/a.png). A second run skips files it has already imported, even if they are in the trash, so an interrupted import can continue where it stopped.

What to know ​

  • Imported files are shared and have no uploader, because the command runs without a signed-in user. They appear under All media, not under My uploads.
  • Thumbnails are built during the import. Larger conversions are queued, so run a worker: see Storage.
  • Duplicate detection is not applied. Two copies of the same file in the source become two items.
  • With tenancy on, pass --tenant and --tenant-model so the records land in the right tenant. See Tenancy.

Checklist: from Curator ​

  1. Back up the database and the storage disk.
  2. Install the package and run its migrations: see Installation.
  3. List every column that holds a Curator id, for example posts.featured_image_id.
  4. Run media-library:import curator --dry-run -v and check the count.
  5. Run the import with one --update for each column, and --map=storage/curator-map.json.
  6. Read the warnings. Fix anything that was skipped, then handle those ids by hand with the map.
  7. Replace Curator fields in your resources with MediaPicker, using the same column names, and Curator display columns with MediaColumn.
  8. For columns that store several ids as JSON, rewrite them yourself using the map file. --update only handles one id per cell.
  9. Start a queue worker, open the library and spot check files and alt text.
  10. Remove Curator once nothing references it.

Checklist: from a plain Spatie setup ​

  1. Back up the database and the storage disk.
  2. Install the package and run its migrations.
  3. Add HasMediaLibrary to the models whose media you are importing.
  4. Run media-library:import spatie --dry-run -v, narrowing with --model and --collection if needed.
  5. Run the import without --move, so your original Spatie media stays until you have checked the result.
  6. Switch reads from $model->getMedia('images') to $model->getMediaLibraryItems('images'), and forms to MediaPicker with relationship('images').
  7. Compare counts per model and collection, then check the pages that show the images.
  8. Remove the old Spatie media yourself when you are happy. --move only deletes originals as they are copied, so a second run with --move does not delete files that an earlier run already imported.

Commercial licence. One licence per production project. Terms · Privacy · Refunds