Removing & syncing
Removals soft-delete by default; pass forceDelete: true to delete permanently:
use RoundlyConsulting\Attributes\Facades\Attributes;
Attributes::for($product)->forget('color'); // soft delete; returns the count removed
Attributes::for($product)->forget(['color', 'size'], forceDelete: true); // permanently
Attributes::for($product)->forgetExcept(['color']); // list<string> of the removed namesThe model methods are shorthand for forget() and forgetExcept() through the same manager:
$product->syncAttributeMeta('color', collect(['is_pretty' => 'yes']));
$product->detachAttribute('color');
$product->detachAttribute('color', forceDelete: true);
$product->detachAttributes(['color', 'size']);
$product->destroyAttributesExcept(['color']);
$product->destroyAttributes(['price']);Syncing
sync() makes the model’s attributes match the given set exactly — attributes outside the set are removed, and each given value is attached or updated:
use RoundlyConsulting\Attributes\Facades\Attributes;
Attributes::for($product)->sync([
'color' => 'black',
'size' => 'large',
]); // exactly color and size remain
Attributes::for($product)->sync(['color' => 'black'], forceDelete: true); // hard-delete the rest
Attributes::for($product)->sync(['color' => 'black'], meta: ['color' => ['hex' => '#000']]);
Attributes::for($product)->sync([]); // remove every attribute
$product->syncAttributes(['color' => 'black']); // model shorthandBehaviour reference
- forget() — and detachAttribute(), detachAttributes(), destroyAttributes() — removes the named attributes and returns how many; AttributeDetached is dispatched once per name that was actually attached (a name that never was is a no-op), and with history enabled a detached revision is recorded.
- forgetExcept() — and destroyAttributesExcept() — removes every attribute not in the keep-list through the same path, so each removal fires AttributeDetached and records a detached revision. It returns the removed names.
- sync() — and syncAttributes() — validates every given value before anything is detached or written, then removes attributes outside the set the same way and attaches each value, all in one transaction, and dispatches AttributesSynced. It returns the attached Attribute models.
- A force-deleting forgetExcept() or sync() also purges previously soft-deleted extras.
- A soft-deleted value gives up its unique slot, so another owner can take it.
Soft-deleted attributes stay recoverable until attributes:prune removes them permanently (see Artisan commands). Attaching a name again after a soft delete restores its row with a fresh value and meta — the old meta is not revived.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.