eloquent-works / fellowship
Fellowship provides elegant friendship and social connection tools for Laravel applications, including friend requests, blocks, mutual friends, and relationship management.
Requires
- php: ^8.2
- illuminate/database: ^12.0 || ^13.0
- illuminate/events: ^12.0 || ^13.0
- illuminate/pagination: ^12.0 || ^13.0
- illuminate/routing: ^12.0 || ^13.0
- illuminate/support: ^12.0 || ^13.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.95
- larastan/larastan: ^3.0
- laravel/pint: ^1.0
- mockery/mockery: ^1.6
- orchestra/testbench: ^10.0 || ^11.0
- phpunit/phpunit: ^11.5 || ^12.0
This package is not auto-updated.
Last update: 2026-07-27 07:16:21 UTC
README
A complete fellowship and social-connection package for Laravel applications.
Laravel Fellowship adds fellowship requests, accepted connections, blocking, mutual fellowships, request expiration, resend cooldowns, lifecycle events, optional web routes, and maintenance commands to your Eloquent models.
$user->sendFellowshipRequestTo($otherUser); $otherUser->acceptFellowshipRequestFrom($user); $user->isFellowshipWith($otherUser);
✨ Highlights
- Send, accept, deny, cancel, and expire fellowship requests
- Create and remove accepted fellowships
- Block and unblock users
- Prevent requests between blocked users
- Retrieve incoming and outgoing requests
- Retrieve accepted and blocked users
- Find and count mutual fellowships
- Configure request expiration and resend cooldowns
- Dispatch lifecycle events for application integrations
- Register optional web routes with
Route::fellowship() - Customize package models, tables, routes, and controllers
- Expire stale pending requests with an Artisan command
📋 Requirements
| Laravel | PHP | Orchestra Testbench |
|---|---|---|
| 12.x | 8.2+ | 10.x |
| 13.x | 8.3+ | 11.x |
📦 Installation
Install Fellowship through Composer:
composer require eloquent-works/fellowship
Publish the configuration and migrations:
php artisan fellowship:install
Publish the optional route snippet during installation:
php artisan fellowship:install --routes
Run the migrations:
php artisan migrate
🧩 Add the Trait
Add HasFellowships to every Eloquent model that can participate in a fellowship:
<?php namespace App\Models; use EloquentWorks\Fellowship\Traits\HasFellowships; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use HasFellowships; }
📨 Fellowship Requests
Send a request:
$request = $user->sendFellowshipRequestTo($otherUser);
Accept or deny an incoming request:
$otherUser->acceptFellowshipRequestFrom($user); $otherUser->denyFellowshipRequestFrom($user);
Cancel an outgoing request:
$user->cancelFellowshipRequestTo($otherUser);
Check whether a request can be sent:
$user->canSendFellowshipRequestTo($otherUser);
🤝 Accepted Fellowships
Check whether two models share an accepted fellowship:
$user->isFellowshipWith($otherUser);
Retrieve accepted fellowships:
$friends = $user->friends(); $count = $user->fellowshipsCount();
Remove an accepted fellowship:
$user->removeFellowship($otherUser);
removeFellowshipWith() remains available as a compatibility alias.
👥 Mutual Fellowships
Retrieve mutual connections:
$mutual = $user->mutualFellowshipsWith($otherUser);
Count mutual connections:
$count = $user->mutualFellowshipsCountWith($otherUser);
Singular compatibility helpers are also available:
$user->mutualFellowshipWith($otherUser); $user->mutualFellowshipCountWith($otherUser);
🚫 Blocking
Block or unblock another user:
$user->blockUser($otherUser); $user->unblockUser($otherUser);
Inspect blocking state:
$user->hasBlocked($otherUser); $user->isBlockedBy($otherUser);
Retrieve blocked users:
$user->blockedUsers(); $user->blockedByUsers();
Blocking removes an existing request or accepted fellowship between the two models and prevents new requests until the blocker unblocks the other user.
🔎 Relationships and Status
Retrieve the stored relationship model:
$fellowship = $user->fellowshipWith($otherUser);
Retrieve its status:
$status = $user->fellowshipStatusWith($otherUser);
The status is one of the package status values, such as pending, accepted, denied, canceled, expired, or blocked; otherwise, it is null.
Request collections:
$user->incomingFellowshipRequests(); $user->outgoingFellowshipRequests();
Relationship queries:
$user->sentFellowships(); $user->receivedFellowships(); $user->acceptedSentFellowships(); $user->acceptedReceivedFellowships(); $user->pendingSentFellowships(); $user->pendingReceivedFellowships();
🛣️ Web Routes
Fellowship does not load web routes automatically. Register them where you want them in routes/web.php:
<?php use Illuminate\Support\Facades\Route; Route::fellowship();
Customize the route group:
Route::fellowship([ 'prefix' => 'connections', 'name' => 'connections.', 'middleware' => ['web', 'auth', 'verified'], ]);
The macro registers routes for sending, accepting, denying, canceling, and removing fellowships, along with blocking and unblocking users.
⚙️ Configuration
Publish the configuration file:
php artisan vendor:publish --tag=fellowship-config
Important defaults:
return [ 'models' => [ 'fellowship' => EloquentWorks\Fellowship\Models\Fellowship::class, 'user' => null, ], 'tables' => [ 'users' => 'users', 'fellowships' => 'fellowships', ], 'routes' => [ 'prefix' => 'fellowship', 'middleware' => ['web', 'auth'], 'name' => 'fellowship.', ], 'expires_after_days' => 30, 'request_cooldown_days' => 7, 'dispatch_events' => true, ];
Set expires_after_days to null when pending requests should never expire. Set request_cooldown_days to null or 0 to disable resend cooldowns.
📣 Events
Fellowship can dispatch the following lifecycle events:
FellowshipRequestSentFellowshipRequestAcceptedFellowshipRequestDeniedFellowshipRequestCanceledFellowshipRequestExpiredFellowshipRemovedUserBlockedUserUnblocked
Use these events for notifications, activity feeds, auditing, achievements, analytics, and other application-specific side effects.
Disable all package events through configuration:
'dispatch_events' => false,
⏳ Expiration and Scheduling
Expire stale pending requests manually:
php artisan fellowships:expire
Process records with a custom chunk size:
php artisan fellowships:expire --chunk=500
Schedule automatic expiration in your application:
use Illuminate\Support\Facades\Schedule; Schedule::command('fellowships:expire')->daily();
📚 Documentation
- Documentation index
- Installation
- Configuration
- Usage
- API reference
- Routes
- Database
- Events
- Commands
- Controller statuses
- Customization
- Testing
- Upgrade guide
- FAQ
✅ Quality Checks
Run the complete quality suite:
composer quality
Or run each check separately:
composer format:test
composer analyse
composer test
Format the package source:
composer format
🔒 Security
Please report security vulnerabilities privately according to SECURITY.md. Do not disclose unresolved vulnerabilities through public GitHub issues.
🤝 Contributing
See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
🙏 Credits
Built by Eloquent Works.
📄 License
Laravel Fellowship is open-source software licensed under the MIT License.