kolirt/laravel-master-model
Laravel Master Model
Laravel Master Model is a powerful package for the Laravel framework that simplifies working with models, particularly in saving relations and uploading files.
This package is designed for developers who want to optimize the process of working with databases and files, reducing code complexity and enhancing performance.
Structure
Getting started
Requirements
- PHP >= 8.1
- Laravel >= 10
Installation
composer require kolirt/laravel-master-model
Setup
Publish config file
php artisan master-model:install
Use the MasterModel trait in your models
use Kolirt\MasterModel\Traits\MasterModel;
class Item extends Model
{
use MasterModel;
}
Console commands
master-model:install- Install master model packagemaster-model:publish-config- Publish the config file
Use cases
Saving files
class Item extends Model
{
use MasterModel;
protected $fillable = [
'image',
];
}
MasterModel automatically saves the file and deletes the old file, if it existed
class ExampleController extends Controller
{
public function index(Request $request, $id)
{
$data = $request->validate([
'image' => 'required|file',
]);
$item = Item::query()->findOrFail($id);
$item->update($data);
}
}
You can specify folder and disk for each file
class Item extends Model
{
use MasterModel;
protected $fillable = [
'image',
];
protected string $upload_model_folder = 'items';
protected array $upload_folders = [
'image' => 'image',
];
protected array $upload_disks = [
'image' => 'public'
];
}
Saving files from third-party resources
You no longer need to worry about saving files from third-party resources, just put the response and MasterModel will save everything for you
class ExampleController extends Controller
{
public function index($id)
{
$file1_url = 'https://png.pngtree.com/png-clipart/20230126/original/pngtree-fresh-red-apple-png-image_8930987.png';
$response = \Illuminate\Support\Facades\Http::get($file1_url);
$file2_url = 'https://cubanvr.com/wp-content/uploads/2023/07/ai-image-generators.webp';
$client = new \GuzzleHttp\Client();
$response2 = $client->get($file2_url);
Item::create([
'image' => $response,
'image2' => $response2
]);
}
}
Deleting files
You can delete files by setting the field to null
$item = Item::query()->first();
$item->update([
'image' => null
]);
To have files deleted automatically, delete data through the model, not through the builder, and don't forget to load the necessary relations in which you want to delete files
If there are files in the relationship and the relationship is deleted not through the model, the files won't be deleted and will clog up storage
$item = Item::query()->with(['phone', 'addresses'])->first();
/**
* All files in the model and in the loaded relations will be deleted
*/
$item->delete();
Files and database transactions
A file operation that cannot be undone waits until the database says it is safe.
Inside a transaction, files a save() or a delete() replaced or removed are deleted from the disk
only after the outermost transaction commits. If the transaction rolls back, those files stay where
they are, and any file the save had just stored is removed again.
DB::transaction(function () use ($item, $request, $order) {
$item->update([
'image' => $request->file('image')
]);
// The old image is still on disk here, the new one is already stored
$order->save(); // throws
// Rollback: the old image survives, the new one is deleted
});
Outside a transaction nothing changed — files are written and deleted immediately, as before.
Three things are worth knowing:
- On rollback the model in memory is restored only for its file attributes.
exists, a generatedid,wasRecentlyCreated,getOriginal()and saved relations stay as the save left them — Laravel does not roll those back either. Reusing the same instance after a rolled back transaction is not supported. - A model is held in memory until its transaction finishes, so saving a large number of models with files inside one transaction grows memory in proportion to the files stored.
- Files are tied to the connection the model writes to. If the model uses one connection and the transaction was opened on another, there is nothing to wait for and the file operation runs immediately.
Saving HasOne, MorphOne relations
You can save HasOne, MorphOne relations in the same way as a file. If relation exists, it will be updated, otherwise it will be created
$item = Item::query()->first();
$item->update([
'phone' => [ // hasOne, morphOne relation
'number' => '1234567890'
]
]);
You can also delete the relation by setting it to null
$item = Item::query()->first();
$item->update([
'phone' => null // hasOne, morphOne relation
]);
Saving HasMany, MorphMany relations
You can save HasMany, MorphMany relations in the same way as a file. If relations exists, it will be updated, otherwise it will be created
$item = Item::query()->first();
$item->update([
'phones' => [ // hasMany, morphMany relations
[ // will be created
'number' => '1234567890'
],
[ // will be updated (id = 1)
'id' => 1,
'number' => '0987654321'
]
]
]);
Saving HasMany, MorphMany relations with sync mode
You can also sync HasMany, MorphMany relations. Unspecified relations will be deleted
$item = Item::query()->first();
$item->update([
'phones' => [ // hasMany, morphMany relations
'mode' => 'sync', // not specified relations will be deleted
'value' => [
[ // will be created
'number' => '1234567890'
],
[ // will be updated (id = 1)
'id' => 1,
'number' => '0987654321'
]
]
]
]);
Saving BelongsToMany relation
$item = Item::query()->first();
$item->update([
'categories' => [1, 2, 3] // belongsToMany relations
]);
$item->update([
'categories' => [ // belongsToMany relation
1 => ['name' => 'Category 1'],
2 => ['name' => 'Category 2'],
3 => ['name' => 'Category 3']
]
]);
Saving BelongsToMany relation with sync mode
You can sync the BelongsToMany relation. Everything that is not specified when saving will be deleted
$item = Item::query()->first();
$item->update([
'categories' => [ // belongsToMany relation
'mode' => 'sync', // not specified relations will be deleted
'value' => [1, 2, 3]
]
]);
$item->update([
'categories' => [ // belongsToMany relation
'mode' => 'sync', // not specified relations will be deleted
'value' => [
1 => ['name' => 'Category 1'],
2 => ['name' => 'Category 2'],
3 => ['name' => 'Category 3']
]
]
]);
Response file
Use the responseFile method to return a file in a controller
class FileController extends Controller
{
public function index()
{
$item = Item::query()->first();
return $item->responseFile('image');
}
}
FAQ
Check closed issues to get answers for most asked questions
License
Other packages
Check out my other packages on my GitHub profile