korridor/laravel-has-many-sync
Installation:
composer require korridor/laravel-has-many-sync
Publish the config (if needed):
php artisan vendor:publish --provider="Korridor\HasManySync\HasManySyncServiceProvider"
First Use Case: Add the trait to your model:
use Korridor\HasManySync\HasManySync;
class Post extends Model
{
use HasManySync;
public function tags()
{
return $this->hasMany(Tag::class);
}
}
Now use syncHasMany() instead of sync():
$post = Post::find(1);
$post->syncHasMany('tags', [1, 2, 3]); // Syncs tags with IDs 1, 2, 3
Key Files:
config/has-many-sync.php (for customization)app/Models/YourModel.php (where you apply the trait)Basic Syncing:
// Sync by IDs
$model->syncHasMany('relation', [1, 2, 3]);
// Sync by full models
$model->syncHasMany('relation', Tag::find([1, 2, 3]));
Bulk Operations:
// Sync for multiple models
Post::where('category', 'news')->get()->each(function ($post) {
$post->syncHasMany('tags', [1, 4, 5]);
});
Conditional Syncing:
if ($request->has('new_tags')) {
$post->syncHasMany('tags', $request->input('new_tags'));
}
Integration with Eloquent Events:
// Listen for sync events
$model->syncHasMany('relation', $data, function ($model, $relation, $data) {
// Custom logic before sync
});
Customizing Behavior:
// Override default behavior in model
public function syncHasMany($relation, $data, $detaching = true, $touch = true)
{
// Custom logic
parent::syncHasMany($relation, $data, $detaching, $touch);
}
API Controllers:
public function update(Request $request, Post $post)
{
$post->syncHasMany('tags', $request->tags);
return $post;
}
Form Requests:
public function rules()
{
return [
'tags' => 'sometimes|array',
];
}
Seeding:
$post = Post::factory()->create();
$post->syncHasMany('tags', Tag::factory()->count(3)->create()->pluck('id'));
Namespace Mismatch:
1.* uses Korridor\HasManyMerged\HasManySync, while 2.* uses Korridor\HasManySync\HasManySync.use statement based on your installed version.Missing Relation:
hasMany, belongsToMany) before using syncHasMany.Detaching Behavior:
detaching = true removes all non-specified records. Set to false to avoid detaching:
$model->syncHasMany('relation', $data, detaching: false);
Touching Timestamps:
touch parameter (default: true) updates the parent model’s updated_at. Disable with:
$model->syncHasMany('relation', $data, touch: false);
Performance with Large Datasets:
SyncHasManyJob::dispatch($model, 'relation', $data)->onQueue('sync');
Check Sync Events:
DB::enableQueryLog();
$model->syncHasMany('relation', $data);
dd(DB::getQueryLog());
Validate Input:
$data is an array of IDs or models. Invalid input may cause silent failures.Model Events:
syncHasMany in your model to add logging or validation:
public function syncHasMany($relation, $data, $detaching = true, $touch = true)
{
$this->validateSyncData($relation, $data);
parent::syncHasMany($relation, $data, $detaching, $touch);
}
Custom Sync Logic:
Model::macro('syncHasManyCustom', function ($relation, $data) {
// Custom logic
$this->syncHasMany($relation, $data);
});
Queueable Sync:
class SyncHasManyJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public function handle()
{
$this->model->syncHasMany($this->relation, $this->data);
}
}
Custom Validation:
protected function validateSyncData($relation, $data)
{
if (!is_array($data)) {
throw new \InvalidArgumentException('Data must be an array.');
}
}
Config Overrides:
config/has-many-sync.php:
'default_detaching' => false,
'default_touch' => false,
How can I help you explore Laravel packages today?