NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Teams for Laravel

Installation

Require the package, then publish and run its migrations — and those of the Roundly packages it builds on. The service provider and the Teams facade alias are auto-discovered:

composer require roundly-consulting/teams-for-laravel

php artisan vendor:publish --tag="options-migrations"
php artisan vendor:publish --tag="contacts-migrations"
php artisan vendor:publish --tag="addresses-migrations"
php artisan vendor:publish --tag="connections-migrations"
php artisan vendor:publish --tag="approvals-migrations"
php artisan vendor:publish --tag="teams-migrations"
php artisan migrate

Publishing is required — none of these packages load their migrations themselves, so a bare php artisan migrate creates no tables. The eight teams migrations publish timestamp-injected and in dependency order (teams first, then the tables whose foreign keys reference it), so they order correctly against your own. Republishing lands on the same files, so --force overwrites in place. Migrations only migrate forward: rolling them back leaves the tables in place.

Why the sibling migrations

Teams reads its per-team settings — join policy, seat cap, default role — from options-for-laravel on every member add and join request, so the options table is needed from the very first Teams::create(). The contacts, addresses, connections and approvals tables back Teams::for($team)->contacts(), ->addresses(), ->connections() and the governed join-request sign-off — see Integrations.

Optional publishing

php artisan vendor:publish --tag="teams-config"         # config/teams.php
php artisan vendor:publish --tag="teams-translations"   # error messages
php artisan vendor:publish --tag="teams-stubs"          # controller, routes, subscriber, Pest file
TagPublishesLands at
teams-migrationsThe eight migrations (required)database/migrations/
teams-configconfig/teams.phpconfig/teams.php
teams-translationsError messages (English and Slovak)lang/vendor/teams/
teams-stubsAcceptInviteControllerapp/Http/Controllers/AcceptInviteController.php
teams-stubsAccept-invite routeroutes/teams.php
teams-stubsTeamEventSubscriberapp/Listeners/TeamEventSubscriber.php
teams-stubsPest matchers bootstraptests/Teams.php

Upgrading from 2.0

Every 2.x addition is opt-in and changes nothing until you switch it on. Two of them need a column: nested teams read teams.parent_id (0007_add_parent_id_to_teams_table) and start dates read team_members.starts_at (0008_add_starts_at_to_team_members_table). Publish the migrations again — files published before are skipped, only the missing ones are added — and migrate before you turn either option on:

php artisan vendor:publish --tag="teams-migrations"   # files published before are skipped
php artisan migrate

If you keyed your teams with a HasUlids or HasUuids subclass of Team and hand-edited the published migrations, set TEAMS_PRIMARY_KEY_TYPE to that type and run php artisan teams:doctor — it checks that the setting, the model and your columns agree. The subclass can stay or go; nothing changes for bigint teams.

Team::hasMember() and members()->has() are deprecated in favour of hasActiveMember() and members()->hasActive(), which ignore expired memberships — see Members.

Before your first team

  • Members with UUID or ULID keys? Set TEAMS_KEY_TYPE before you migrate. Teams themselves keyed by UUID or ULID? Set TEAMS_PRIMARY_KEY_TYPE too — see Configuration.
  • Add the HasTeams trait to your user model — see Model traits.
  • Register your roles in a service provider, including the owner, admin and member keys the package assigns by default — see Roles.

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 crypto

By 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.