Skip to content

v1.0.0 — Initial Stable Release

Latest

Choose a tag to compare

@SignalByNick SignalByNick released this 26 Jul 09:20

Laravel Fellowship v1.0.0 🎉

The first stable release of Laravel Fellowship.

Laravel Fellowship provides a complete social-connection system for Laravel applications, including fellowship requests, accepted connections, blocking, mutual fellowships, request expiration, resend cooldowns, lifecycle events, configurable routes, and relationship-management helpers.

This release establishes the package's initial public API and provides a production-focused foundation for adding social relationships to Laravel applications.

✨ Features

  • Send fellowship requests
  • Accept incoming fellowship requests
  • Deny incoming fellowship requests
  • Cancel outgoing fellowship requests
  • Remove accepted fellowships
  • Block and unblock users
  • Prevent requests between blocked users
  • Retrieve accepted fellowships
  • Retrieve incoming pending requests
  • Retrieve outgoing pending requests
  • Retrieve users blocked by the current user
  • Retrieve users who blocked the current user
  • Check fellowship status between two users
  • Count accepted fellowships
  • Find mutual fellowships
  • Count mutual fellowships
  • Configurable request expiration
  • Configurable resend cooldowns
  • Optional lifecycle events
  • Configurable models and database tables
  • Optional package-provided web routes
  • Artisan installation and expiration commands
  • Transactional relationship updates
  • Laravel package auto-discovery
  • PHPUnit, PHPStan, and formatting support
  • Complete package documentation

🤝 Fellowship Requests

Users can send, accept, deny, and cancel fellowship requests through the HasFellowships trait.

use EloquentWorks\Fellowship\Traits\HasFellowships;

class User extends Authenticatable
{
    use HasFellowships;
}

Send a fellowship request:

$request = $user->sendFellowshipRequestTo($recipient);

Accept an incoming request:

$recipient->acceptFellowshipRequestFrom($user);

Deny an incoming request:

$recipient->denyFellowshipRequestFrom($user);

Cancel an outgoing request:

$user->cancelFellowshipRequestTo($recipient);

Laravel Fellowship prevents:

  • Sending requests to yourself
  • Duplicate active requests
  • Requests between blocked users
  • Re-sending requests during the configured cooldown
  • Accepting expired requests
  • Creating duplicate relationship pairs

✅ Accepted Fellowships

Retrieve a user's accepted fellowships:

$fellowships = $user->fellowships();

Count accepted fellowships:

$count = $user->fellowshipsCount();

Check whether two users are connected:

$user->isFellowWith($otherUser);

Retrieve the relationship status:

$status = $user->fellowshipStatusWith($otherUser);

Retrieve the underlying relationship record:

$fellowship = $user->fellowshipWith($otherUser);

Remove an accepted fellowship:

$user->removeFellowship($otherUser);

👥 Mutual Fellowships

Retrieve mutual fellowships shared by two users:

$mutual = $user->mutualFellowshipsWith($otherUser);

Count mutual fellowships:

$count = $user->mutualFellowshipsCountWith($otherUser);

These helpers are useful for:

  • Social discovery
  • Profile pages
  • Suggested connections
  • Shared-contact displays
  • Community and collaboration features

🚫 Blocking

Block another user:

$user->blockUser($otherUser);

Unblock a user:

$user->unblockUser($otherUser);

Check block direction:

$user->hasBlocked($otherUser);
$user->isBlockedBy($otherUser);

Retrieve blocked users:

$blocked = $user->blockedUsers();
$blockedBy = $user->blockedByUsers();

Blocking prevents new fellowship requests until the blocking user removes the block.

⏳ Request Expiration

Pending fellowship requests expire automatically according to the configured lifetime:

'expires_after_days' => 30,

Disable automatic expiration:

'expires_after_days' => null,

Expired requests:

  • Are excluded from active pending-request queries
  • Cannot be accepted
  • Can dispatch a lifecycle event
  • Can be processed through the package command

Expire old requests manually:

php artisan fellowship:expire

Schedule automatic cleanup:

use Illuminate\Console\Scheduling\Schedule;

protected function schedule(Schedule $schedule): void
{
    $schedule->command('fellowship:expire')->daily();
}

🔁 Request Cooldowns

Laravel Fellowship can prevent users from immediately re-sending a request after it has been denied, canceled, or expired.

'request_cooldown_days' => 7,

Disable cooldown enforcement:

'request_cooldown_days' => null,

Applications can check eligibility before presenting a request button:

$user->canSendFellowshipRequestTo($otherUser);

📣 Lifecycle Events

Laravel Fellowship can dispatch events for important relationship changes.

Included events cover:

  • Fellowship request sent
  • Fellowship request accepted
  • Fellowship request denied
  • Fellowship request canceled
  • Fellowship request expired
  • Fellowship removed
  • User blocked
  • User unblocked

Events can power:

  • Notifications
  • Activity feeds
  • Audit logs
  • Analytics
  • Queued jobs
  • Application-specific integrations

Disable package event dispatching:

'dispatch_events' => false,

🔒 Transactional Updates

Relationship-changing operations use database transactions and row locking where appropriate.

This protects workflows such as:

Validate relationship
→ Lock existing pair
→ Apply status change
→ Save relationship
→ Dispatch lifecycle event

The package also stores a deterministic pair key for each relationship pair, helping prevent duplicate records regardless of which user initiated the relationship.

🌐 Optional Web Routes

Laravel Fellowship does not force routes into the application automatically.

Register the bundled routes where needed:

use Illuminate\Support\Facades\Route;

Route::fellowship();

Default route configuration:

'routes' => [
    'prefix' => 'fellowship',
    'middleware' => ['web', 'auth'],
    'name' => 'fellowship.',
],

Applications remain free to use:

  • The bundled controller routes
  • Custom controllers
  • Livewire components
  • Inertia actions
  • JSON APIs
  • Direct model methods

⚙️ Configuration

Publish the configuration file:

php artisan vendor:publish --tag=fellowship-config

Laravel Fellowship supports configuration for:

  • Fellowship model
  • User model
  • Users table
  • Fellowships table
  • Route prefix
  • Route middleware
  • Route-name prefix
  • Route controller
  • Request expiration
  • Request cooldown
  • Lifecycle-event dispatching

🗃️ Database

Publish the package migrations:

php artisan vendor:publish --tag=fellowship-migrations

Run migrations:

php artisan migrate

The relationship record stores information such as:

  • Sender ID
  • Recipient ID
  • Deterministic pair key
  • Relationship status
  • Acceptance timestamp
  • Expiration timestamp
  • Creation and update timestamps

Supported lifecycle statuses include:

pending
accepted
denied
canceled
expired
blocked

🛠️ Installation Command

Install the package resources with:

php artisan fellowship:install

Run migrations during installation:

php artisan fellowship:install --migrate

🧪 Quality and Testing

Laravel Fellowship includes automated coverage for:

  • Sending requests
  • Duplicate-request prevention
  • Accepting requests
  • Denying requests
  • Canceling requests
  • Request expiration
  • Resend cooldowns
  • Removing fellowships
  • Blocking and unblocking
  • Block ownership
  • Mutual fellowships
  • Lifecycle events
  • Event configuration
  • Web-controller routes
  • Artisan commands
  • Route registration
  • Service-provider behavior

The package includes scripts for:

composer format
composer format:test
composer analyse
composer test
composer quality

📚 Documentation

The documentation includes dedicated guides for:

  • Installation
  • Configuration
  • Usage
  • API reference
  • Routes
  • Controller statuses
  • Commands
  • Events
  • Database structure
  • Customization
  • Testing
  • Upgrade guidance
  • Frequently asked questions

Start with:

docs/README.md

✅ Supported Versions

  • PHP 8.2 or newer
  • Laravel 12
  • Laravel 13

🚀 Installation

Install Laravel Fellowship through Composer:

composer require eloquent-works/fellowship

Install package resources and run migrations:

php artisan fellowship:install --migrate

Add the trait to the application's authenticatable model:

use EloquentWorks\Fellowship\Traits\HasFellowships;

class User extends Authenticatable
{
    use HasFellowships;
}

🧰 Quality Checks

Before releasing or deploying, run:

composer validate --strict
composer audit
composer format:test
composer analyse
composer test

Or run the complete package quality suite:

composer quality

❤️ Thank You

Thank you for using Laravel Fellowship.

Feedback, bug reports, feature requests, documentation improvements, and pull requests are always welcome.