Ownership
A team’s owner is a polymorphic relation, so any model can own a team. Check it from either side:
$team->owner; // the owning model, or null
$team->isOwnedBy($user); // bool
$user->ownsTeam($team); // bool — via the HasTeams trait
Teams::for($team)->transferOwnershipTo($newOwner);Transferring ownership
transferOwnershipTo() runs TransferOwnershipAction in one transaction:
- The new owner is seated first, ensured to be a member with roles.owner.
- The previous owner (if any, and not the same model) stays on the team, demoted to roles.admin — admin by default.
- owner_type and owner_id move to the new owner.
- TeamOwnershipTransferred fires with the team, the previous owner (nullable) and the new owner.
The transfer is all-or-nothing. If the new owner can’t be seated — the team’s MaxSeats is reached — it throws TeamsException and the owner, the roster and every role stay exactly as they were.
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Teams\Events\TeamOwnershipTransferred;
Event::listen(function (TeamOwnershipTransferred $event): void {
// $event->team, $event->previousOwner (nullable), $event->newOwner
});The owner ability
A first-class owner ability removes hand-rolled owner-only permissions. It checks ownership itself, not a role, so it works even if your owner role grants nothing:
$user->can('teams.owner', $team); // true only for the owner
Gate::authorize('teams.owner', $team); // 403 for everyone else@teamOwner($team)
<button>Delete team</button>
@endteamOwnerThe ability name is gate.prefix + gate.owner_ability — teams.owner by default.
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.