Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Porter Laravel Package

hdaklue/porter

Lightweight, fast access control for Laravel with roles modeled as domain logic. Assign roles between any Assignable (users/teams) and Roleable (projects/docs) via a Roster. Supports cross-database role assignments for complex, distributed architectures.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by installing the package via Composer: composer require hdaklue/porter. Run the migration: php artisan porter:migrate (creates a single porters table for assignments). Define your first role class by extending Hdaklue\Porter\Role\BaseRole (e.g., app/Roles/ProjectManager.php), implementing getName() and optionally business methods like canEditMilestones(). Next, mark your assignable models (e.g., User) and roleable models (e.g., Project) with the respective traits: Assignable and Roleable. Your first use case: assign a user to a project with a role and check access inline:

Porter::assign($user, $project, ProjectManager::class);
if ($user->getAssignmentOn($project)->canEditMilestones()) { /* ... */ }

Look first at the docs/suggested-usage.md and the LeadDeveloper example in the README to internalize the Assignable–Roleable–Roster mental model.

Implementation Patterns

  • Contextual Role Logic: Encode business rules directly in role classes — avoid generic permissions. A role’s methods define capabilities (e.g., canExportData(int $limit): bool, getRetentionDays(): int), enabling type-safe, discoverable access checks.
  • Assignment Key Abstraction: Use explicit key identifiers (ProjectManager::class, 'owner') and let Porter handle casting via RoleCast. Prefer class-based keys for IDE autocomplete and refactor safety.
  • Cross-Database Scenarios: If User lives on db1 and Project on db2, define separate database connections in config/database.php, and Porter auto-detects and issues multi-connection queries—no extra code required. For custom behavior, override resolveConnection() in your role class.
  • Blade & Gates Integration: Use @can('view', $project, ['as' => ProjectManager::class]) and middleware Route::post('/projects/{id}', ...)->middleware('porter:assignable,user,roleable,project,ProjectManager'). Gates automatically resolve assignments if the Gate::after() callback is configured (see docs/laravel-integration.md).
  • Bulk & Batch Assignments: Assign multiple roleables to one assignable in bulk:
    Porter::assign($team, [$projectA, $projectB], Developer::class);
    Porter::revoke($user, $document, 'viewer');
    Porter::revokeAll($user); // revoke all assignments for user
    

Gotchas and Tips

  • Assignments Are Tied to Instances, Not Keys Alone: Porter::assign($user, $project, Developer::class) creates one row per pair (user_id, project_id, key)—not a global mapping. Reassigning a different project requires a new assignment.
  • Encrypted Keys for Security: The key column in porters is encrypted by default. Use Porter::assign($user, $project, 'plain_key') only if absolutely necessary (and only in dev/test), or set encrypt_keys to false in config/porter.php.
  • Caching: Porter uses Laravel’s cache driver to store assignments. Clear cached assignments after mass changes using Porter::clearCache($user, $project). Disable caching only if absolutely necessary (cache_assignments => false).
  • No Database Joins: Access checks via $user->getAssignmentOn($project) are O(1) cache lookups. If you query manually (e.g., whereHas('assignments')), ensure you’re not triggering N+1—use with('assignments') or Porter::hasAssignment($user, $project, Role::class).
  • Extensibility Hooks: Override resolveAssignable(), resolveRoleable(), and resolveConnection() in your custom BaseRole subclasses to support tenant scoping, soft-deletion awareness, or fallback strategies in distributed systems.
  • Multitenancy Caveat: If using tenant-aware assignments, always assign tenant entities (e.g., Tenant::class) as assignable or roleable where needed. The package validates tenant integrity, but you must ensure tenant_id consistency across models in config/porter.php.
  • Performance Tip: For high-volume checks (e.g., listing 1000 projects with per-user permissions), prefetch assignments in bulk:
    $projects = Project::with(['assignments' => fn($q) => $q->whereAssignable($user)])->get();
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation
uri-template/tests