luchavez / simple-files
A simple approach to adding polymorphic files such as images to any Eloquent models in Laravel 9|10
Installs: 1 578
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/luchavez/simple-files
Requires
- php: ^8.0
- ext-fileinfo: *
- illuminate/support: ~9|~10
- league/flysystem-path-prefixing: ^3.10
- league/flysystem-read-only: ^3.10
- luchavez/starter-kit: ^1.0
- spatie/laravel-tags: ^4.5
Requires (Dev)
- orchestra/testbench: ~7|~8
- phpunit/phpunit: ~9.0
- roave/security-advisories: dev-latest
Suggests
This package is auto-updated.
Last update: 2025-10-13 17:30:08 UTC
README
Introduction
Implementing a public-private filesystem structure to your Laravel application can be a hassle. But with "luchavez/simple-files", it's easy! This package is built with that in mind so that you can proceed with more important things in your project. It's perfect for Laravel applications that need to work with files. And the best part? It can process not only uploaded files but also Base64 strings and image URLs! Plus, it's especially effective on AWS S3 buckets. Try it out today and see how it can help you!
Check out the examples below to get a clearer picture.
Installation
Via Composer
$ composer require luchavez/simple-files:^1.0.0
Setting Up
- 
Add the HasFilesTrait trait to all the Eloquent models that can own files. 
- 
Add these variables to .envfile if you want to override the default values.
| Variable Name | Default Value | 
|---|---|
| SF_FILESYSTEM_DISK | config('filesystems.default') | 
| SF_EXPIRE_AFTER | 1 day | 
| SF_PUBLIC_DIRECTORY | public | 
| SF_PRIVATE_DIRECTORY | private | 
Usage
SimpleFiles
The package provides a service called SimpleFiles which you can use by calling its helper functions:
- simpleFiles()
- simple_files()
Here's the list of its available methods.
| Method Name | Return Type | Description | 
|---|---|---|
| getFileSystemDisk | string | gets the filesystem disk | 
| getDisk | string | shortcut for getFileSystemDiskmethod | 
| getExpireAfterUnit | string | gets the time unit for temporary URL expiration | 
| getExpireAfterValue | string | gets the time value for temporary URL expiration | 
| getExpireAfter | Illuminate\Support\Carbon | gets the Carbonequivalent ofgetExpireAfterUnit()andgetExpireAfterValue() | 
| getPublicDirectory | string | gets the specified publicdirectory | 
| getPrivateDirectory | string | gets the specified privatedirectory | 
| shouldOverwriteOnExists | bool | decides whether to overwrite or not when it already exists | 
| getFileSystemAdapter | Illuminate\Contracts\Filesystem\Filesystem | gets the filesystem adapter | 
| getAdapter | Illuminate\Contracts\Filesystem\Filesystem | shortcut for getFileSystemAdaptermethod | 
| getPublicAdapter | Illuminate\Contracts\Filesystem\Filesystem | uses getFileSystemAdaptermethod with$is_publictotrue | 
| getPrivateAdapter | Illuminate\Contracts\Filesystem\Filesystem | uses getFileSystemAdaptermethod with$is_publictofalse | 
| store | Luchavez\SimpleFiles\Models\File or Collection or null | stores file/s to specified publicorprivatedirectory | 
| storePublicly | Luchavez\SimpleFiles\Models\File or Collection or null | uses store()method with$is_publictotrue | 
| storePrivately | Luchavez\SimpleFiles\Models\File or Collection or null | uses store()method with$is_publictofalse | 
| getContentsFromURL | string or null | gets contents by using file_get_contents() | 
| getContentsFromBase64 | string or null | gets contents by using base64_decode() | 
| getFiles | array | gets files list from specified publicorprivatedirectory | 
| getPublicFiles | array | uses getFiles()method with$is_publictotrue | 
| getPrivateFiles | array | uses getFiles()method with$is_publictofalse | 
| getFile | string or null | gets file contents | 
| getFilePublicly | string or null | uses getFile()method with$is_publictotrue | 
| getFilePrivately | string or null | uses getFile()method with$is_publictofalse | 
| putFile | string or null | uploads file to specified publicorprivatedirectory | 
| putFilePublicly | string or null | uses putFile()method with$is_publictotrue | 
| putFilePrivately | string or null | uses putFile()method with$is_publictofalse | 
| putFileAs | string or null | uploads file to specified publicorprivatedirectory | 
| putFilePubliclyAs | string or null | uses putFileAs()method with$is_publictotrue | 
| putFilePrivatelyAs | string or null | uses putFileAs()method with$is_publictofalse | 
| exists | bool | checks if file exists on specified publicorprivatedirectory | 
| existsPublicly | bool | uses exists()method with$is_publictotrue | 
| existsPrivately | bool | uses exists()method with$is_publictofalse | 
| delete | bool | deletes file/s from specified publicorprivatedirectory | 
| deletePublicly | bool | uses delete()method with$is_publictotrue | 
| deletePrivately | bool | uses delete()method with$is_publictofalse | 
| getDirectories | array | gets files list from specified publicorprivatedirectory | 
| getPublicDirectories | array | uses getDirectories()method with$is_publictotrue | 
| getPrivateDirectories | array | uses getDirectories()method with$is_publictofalse | 
| deleteFiles | bool | deletes files from specified publicorprivatedirectory | 
| deletePublicFiles | bool | uses deleteFiles()method with$is_publictotrue | 
| deletePrivateFiles | bool | uses deleteFiles()method with$is_publictofalse | 
| relateFileModelTo | void | dynamically build relationship from any model to the Filemodel | 
| generateUrl | void | create a new url or temporary url to a Luchavez\SimpleFiles\Models\File instance | 
HasFilesTrait
The package also provides HasFilesTrait which you can use on Eloquent models that you want to have files or images.
- If a User model needs profile pictures...
use Luchavez\SimpleFiles\Traits\HasFilesTrait;
class User extends Authenticatable
{
    use HasFactory, Notifiable, HasFilesTrait;
...
- Or, if a Company model needs logos...
use Luchavez\SimpleFiles\Traits\HasFilesTrait;
class Company extends Model
{
    use HasFactory, HasFilesTrait;
...
- Or, if a Food model needs some Instagram-worthy images...
use Luchavez\SimpleFiles\Traits\HasFilesTrait;
class Food extends Model
{
    use HasFactory, HasFilesTrait;
...
Here's the list of methods that will be added to Eloquent models.
| Method Name | Return Type | Description | 
|---|---|---|
| files | Illuminate\Database\Eloquent\Relations\MorphToMany | gets all files | 
| images | Illuminate\Database\Eloquent\Relations\MorphToMany | gets all image files | 
| nonImages | Illuminate\Database\Eloquent\Relations\MorphToMany | gets all non-image files | 
| fileables | Illuminate\Database\Eloquent\Relations\MorphMany | gets all fileables | 
| fileable | Illuminate\Database\Eloquent\Relations\MorphOne | gets latest fileable | 
| imageables | Illuminate\Database\Eloquent\Relations\MorphMany | gets all imageables | 
| imageable | Illuminate\Database\Eloquent\Relations\MorphOne | gets latest imageable | 
| nonImageables | Illuminate\Database\Eloquent\Relations\MorphMany | gets all non-imageables | 
| nonImageable | Illuminate\Database\Eloquent\Relations\MorphOne | gets latest non-imageable | 
| attachFiles | void | attaches file/s to model | 
| attachPublicFiles | void | attaches file/s to model | 
| attachPrivateFiles | void | attaches file/s to model | 
| syncFiles | void | syncs file/s to model | 
| syncPublicFiles | void | syncs file/s to model | 
| syncPrivateFiles | void | syncs file/s to model | 
| detachFiles | void | detaches file/s to model | 
| detachPublicFiles | void | detaches file/s to model | 
| detachPrivateFiles | void | detaches file/s to model | 
Examples
Note: In case you did not specify the user who uploaded the file, it will try to get the authenticated user via auth()->user().
Here are the .env variables used in this example:
SF_FILESYSTEM_DISK=s3 SF_PUBLIC_DIRECTORY=public/dev/dummy SF_PRIVATE_DIRECTORY=private/dev/dummy SF_EXPIRE_AFTER=1 day
Uploading files
Let's start first by creating a public route /api/files. Use storePublicly() and storePrivately() methods of simpleFiles() global helper function to store the files on public/dev/dummy and private/dev/dummy directories respectively.
- Using storePublicly()with$request->user()as uploader.
Route::post('/files', function (Request $request) {
    $file = $request->file;
    $user = $request->user();
    
    return simpleFiles()->storePublicly(file: $file, user: $user)->toArray();
});
- Using storePrivately()with$request->user()as uploader.
Route::post('/files', function (Request $request) {
    $file = $request->file;
    $user = $request->user();
    
    return simpleFiles()->storePrivately(file: $file, user: $user)->toArray();
});
Once that is set up, we can use Postman to upload files to the route above.
- Here's an example of normal FormDatafile upload usingstorePublicly().
- Here's an example of normal FormDatafile upload usingstorePrivately().
- Here's an example of Base64encoded file upload usingstorePublicly().
- Here's an example of Base64encoded file upload usingstorePrivately().
- Here's an example of file upload from URLusingstorePublicly().
- Here's an example of file upload from URLusingstorePrivately().
Note: If you will open an expired url, you'll receive a Request has expired error.
Attaching files
To attach an uploaded file to a model, use the attachFiles() method from HasFilesTrait.
- If a User model needs profile pictures...
Route::post('upload-files', function (Request $request) {
    $user = \App\Models\User::query()->first();
    $for_upload = $request->file;
    
    // You can attach like this...
    $file = simpleFiles()->storePublicly(file: $for_upload);
    $user->attachFiles(file: $file);
    
    // Or using a one-liner...
    $user->attachPublicFiles(file: $for_upload)
    
    return simpleResponse()->message('Successfully attached files.')->generate();
});
- Or, if a Company model needs logos...
Route::post('upload-files', function (Request $request) {
    $company = \App\Models\Company::query()->first();
    $for_upload = $request->file;
    
    // You can attach like this...
    $file = simpleFiles()->storePublicly(file: $for_upload);
    $company->attachFiles(file: $file);
    
    // Or using a one-liner...
    $company->attachPublicFiles(file: $for_upload)
    
    return simpleResponse()->message('Successfully attached files.')->generate();
});
- Or, if a Food model needs some Instagram-worthy images...
Route::post('upload-files', function (Request $request) {
    $food = \App\Models\Food::query()->first();
    $for_upload = $request->file;
    
    // You can attach like this...
    $file = simpleFiles()->storePublicly(file: $for_upload);
    $food->attachFiles(file: $file);
    
    // Or using a one-liner...
    $food->attachPublicFiles(file: $for_upload)
    
    return simpleResponse()->message('Successfully attached files.')->generate();
});
Change log
Please see the changelog for more information on what has changed recently.
Testing
$ composer test
Contributing
Please see contributing.md for details and a todolist.
Security
If you discover any security related issues, please email author@email.com instead of using the issue tracker.
Credits
License
MIT. Please see the license file for more information.








