escolalms/images
EscolaLMS Images is a Laravel package for image uploads, storage, and processing in EscolaLMS applications. It provides configurable storage disks, image conversion and resizing, and API integration for managing image assets across your platform.
The 0.1.24 release is a patch bump with no documented functional changes (release notes only link to the compare diff), so treat the assessment below as covering the package as it stands at this version. Before upgrading from 0.1.23, open the compare link and skim the diff — in a 0.x package a "patch" can still carry a signature change.
Install and wire it up in roughly this order:
composer require escolalms/images
php artisan vendor:publish --tag=images_config
php artisan vendor:publish --tag=images_migrations
php artisan migrate
Package discovery registers the service provider; there is normally no manual config/app.php edit needed. If your app has a custom namespace or you are running inside a monolith with dont-discover, register the ImagesServiceProvider explicitly.
Where to look first, in this order:
config/images.php — storage disk, conversion/thumbnail definitions, allowed mime types, and the model/service bindings.src/Models/Image.php and the migration — this tells you the real column names (imageable_id / imageable_type, path, ordering, metadata) which everything else depends on.src/Contracts/* — the image service contract; this is your extension point.src/Http/Controllers and the package route file — confirm the actual endpoint paths and middleware before writing frontend code.php artisan route:list --path=images to see what is genuinely exposed in your app after middleware groups are applied.The first use case to get working end-to-end is usually: attach a cover/hero image to an existing model (Course, Product, User), upload it through the package API, and render the resulting URL in a Blade/Inertia/Vue view. Doing that thin slice first exposes the disk configuration, auth middleware, and response shape issues all at once.
Attach images to your own models via the polymorphic relation. Add the package's HasImages-style trait to the model, then work through the relation rather than touching the images table directly:
class Course extends Model
{
use HasImages;
}
$course->images; // collection
$course->images()->create([...]); // if the trait exposes the morph relation
If the package does not ship a convenience attach() helper, wrap the service in your own action class so the disk, mime validation, and conversion logic live in one place instead of being repeated across controllers.
Keep uploads behind the package's own authorization. EscolaLMS packages consistently lean on spatie/laravel-permission plus Sanctum. Gate image creation on a permission (e.g. images_create) in the route middleware group rather than checking ownership inside the controller — it keeps behaviour consistent with the rest of the LMS modules and means admin panels and student surfaces behave predictably.
Bind the service, don't new it. Resolve the image service contract from the container in your own controllers/jobs:
public function __construct(private ImageServiceContract $images) {}
This is the cheapest way to swap in a decorator later (CDN rewriting, watermarking, virus scanning) without editing vendor code or forking.
Store the identifier, derive the URL. Persist the image record, not an absolute URL. When you serialize API responses, map through your API Resource so the URL is generated at read time from the configured disk — this is what makes a later move from public disk to S3 or a CDN a config change instead of a data migration.
Handle conversions asynchronously if you generate many sizes. If the config defines several conversions, dispatch your own queued job that calls the service rather than doing it inline in a request. Image processing is the most common cause of request timeouts in LMS-style admin panels where a bulk import uploads hundreds of images.
Integration tip for tests: use Storage::fake('public') (or whichever disk is configured) plus UploadedFile::fake()->image('cover.jpg'), and assert on the database record rather than on file existence — the package may write through a different flysystem adapter than the one your assertion expects.
0.x is not stable semver. Pin with "escolalms/images": "~0.1.24" and read the compare diff before any bump. The 0.1.24 notes give you nothing to go on, so the diff is the changelog.php artisan config:clear after publishing. Laravel's config cache silently keeps the old images.php values, and the symptom looks like "my disk setting is ignored" rather than a caching problem.storage:link is required for the public disk; on S3 the visibility and url settings must both be right or you get 403s on thumbnails while originals load fine.intervention/image major your lockfile resolved. If thumbnails throw DriverException or "GD not installed"-adjacent errors after a composer update, check the resolved Intervention version before debugging the package.Image row does not necessarily remove the underlying file. If you care about storage cost, delete the file explicitly (or listen to the model's deleted event) and add a scheduled cleanup for rows whose files are missing and vice versa.utf8mb4, a default VARCHAR(255) morph type plus a long namespace will blow the index limit. Use morphs() with the shorter index length, or store a morph map alias via Relation::enforceMorphMap().config/images.php and add a FormRequest with image|mimes:...|max:... in your own layer.vendor/.route:list --path=images (is the route even registered?), the storage/logs/laravel.log entry from the package's exception handler, the resolved disk via Storage::disk(config('images.disk'))->path(''), and finally php artisan about to confirm the provider booted.How can I help you explore Laravel packages today?