Appearance
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=LegacyEvery 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
| Option | Applies to | Meaning |
|---|---|---|
source | all | spatie, curator or directory. |
path | directory | Folder to import, relative to the disk root. |
--disk= | directory | Disk to read from. Defaults to the library disk. |
--model=* | spatie | Only media attached to these model classes. Repeat for several. |
--collection=* | spatie | Only these Spatie collections. Repeat for several. |
--move | spatie | Delete the original Spatie media after it is copied. |
--table= | curator | Table holding the Curator rows. Defaults to curator. |
--update=* | curator | A table.column whose values are rewritten to the new ids. Repeat for several. |
--folder= | all | Put everything into this folder, created when missing. |
--map= | all | Write a JSON map of old id to new library id to this file. |
--tenant= | all | Tenant key to assign to the imported records. |
--tenant-model= | all | Tenant model class. Required with --tenant. |
--dry-run | all | Count what would be imported and write nothing. |
Spatie media
bash
php artisan media-library:import spatieThis 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.
altandcaptionare read from the media's custom properties. - Without
--folder, files go intoImported/<ModelName>, for exampleImported/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_idThis 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=LegacyThis 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 -vA 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
--tenantand--tenant-modelso the records land in the right tenant. See Tenancy.
Checklist: from Curator
- Back up the database and the storage disk.
- Install the package and run its migrations: see Installation.
- List every column that holds a Curator id, for example
posts.featured_image_id. - Run
media-library:import curator --dry-run -vand check the count. - Run the import with one
--updatefor each column, and--map=storage/curator-map.json. - Read the warnings. Fix anything that was skipped, then handle those ids by hand with the map.
- Replace Curator fields in your resources with
MediaPicker, using the same column names, and Curator display columns withMediaColumn. - For columns that store several ids as JSON, rewrite them yourself using the map file.
--updateonly handles one id per cell. - Start a queue worker, open the library and spot check files and alt text.
- Remove Curator once nothing references it.
Checklist: from a plain Spatie setup
- Back up the database and the storage disk.
- Install the package and run its migrations.
- Add
HasMediaLibraryto the models whose media you are importing. - Run
media-library:import spatie --dry-run -v, narrowing with--modeland--collectionif needed. - Run the import without
--move, so your original Spatie media stays until you have checked the result. - Switch reads from
$model->getMedia('images')to$model->getMediaLibraryItems('images'), and forms toMediaPickerwithrelationship('images'). - Compare counts per model and collection, then check the pages that show the images.
- Remove the old Spatie media yourself when you are happy.
--moveonly deletes originals as they are copied, so a second run with--movedoes not delete files that an earlier run already imported.