PHPackages                             artisan-build/turbulence - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. artisan-build/turbulence

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

artisan-build/turbulence
========================

Scaffolding for organizational structures

081↓50%PHPCI failing

Since Oct 13Pushed 6mo ago2 watchersCompare

[ Source](https://github.com/artisan-build/turbulence)[ Packagist](https://packagist.org/packages/artisan-build/turbulence)[ RSS](/packages/artisan-build-turbulence/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

[![Artisan Build Package Turbulence Logo](https://github.com/artisan-build/turbulence/raw/HEAD/art/turbulence.png)](https://github.com/artisan-build/turbulence/raw/HEAD/art/turbulence.png)

Turbulence
==========

[](#turbulence)

Scaffolding for organizational structures in Laravel applications

Warning

This package is currently under active development, and we have not yet released a major version. Once a 0.\* version has been tagged, we strongly recommend locking your application to a specific working version because we might make breaking changes even in patch releases until we've tagged 1.0.

Overview
--------

[](#overview)

Turbulence provides a flexible scaffolding system for building multi-account organizational structures in Laravel applications. It offers a clean separation between user authentication and account management, allowing users to belong to multiple accounts with different roles and permissions.

**Key Features:**

- Multi-account support with user role management
- Flexible organizational unit modeling
- Account session management with URL-based context switching
- Automated installation with Rector-based code transformation
- Profile extension system for accounts and users
- Built-in role-based permissions

Requirements
------------

[](#requirements)

- PHP 8.3+
- Laravel 11.36+ or Laravel 12+
- Verbs package (dev-main)

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require artisan-build/turbulence
```

### Running the Installer

[](#running-the-installer)

Turbulence includes an automated installer that sets up your application:

```
php artisan turbulence:install
```

The installer will:

1. Install Rector (if not already installed)
2. Publish the configuration file
3. Copy base models (Account, AccountProfile) to your app
4. Add the `HasAccounts` trait to your User model
5. Add a `role` cast to your User model for the `UserRoles` enum
6. Add `current_account_id` column to your users table

If you need to run the installer again (for example, after making manual changes), use the `--force` flag:

```
php artisan turbulence:install --force
```

### Running Migrations

[](#running-migrations)

After installation, run the migrations to create the necessary database tables:

```
php artisan migrate
```

This creates:

- `profiles` table - User profile information
- `organizational_units` table - Flexible organizational structure
- Adds `current_account_id` and `role` columns to your users table

Configuration
-------------

[](#configuration)

The configuration file is published to `config/turbulence.php`:

```
return [
    'installed' => true,

    // Specify your User model
    'user_model' => \App\Models\User::class,

    // Specify your Account model
    'account_model' => \App\Models\Account::class,

    // Account session URL configuration
    'account_session_urls' => [
        // Enable URL-based account context switching
        'enabled' => false,

        // Index-based URL key (e.g., /u/0/dashboard)
        // Loads the first account from session('accounts')
        'index_key' => 'u',

        // ID-based URL key (e.g., /i/123/dashboard)
        // Loads account by ID (for impersonation)
        'id_key' => 'i',
    ],
];
```

Core Concepts
-------------

[](#core-concepts)

### Accounts

[](#accounts)

Accounts are the primary organizational container in Turbulence. Users can belong to multiple accounts, and the `Account` model intentionally has minimal columns - just enough to associate it with a user.

```
// The Account model provides the relationship to users
$account = Account::find(1);
$user = $account->user;
```

> **Important:** Do not add custom columns to the accounts table. Use the `AccountProfile` model instead.

### Account Profiles

[](#account-profiles)

Account profiles store all additional information about an account. This separation keeps the account structure clean and extensible:

```
// Extend AccountProfile with your custom fields
class AccountProfile extends Model
{
    protected $fillable = ['company_name', 'industry', 'size'];

    public function account()
    {
        return $this->belongsTo(Account::class);
    }
}
```

### User Accounts

[](#user-accounts)

Users can have multiple accounts and switch between them. The `HasAccounts` trait provides the necessary functionality:

```
// Access user's accounts
$accounts = $user->accounts;

// Get current account
$currentAccount = $user->account;

// Switch to a different account
$user->switchAccount($account);

// Check if user owns an account
if ($user->ownsAccount($account)) {
    // Allow access
}
```

### User Roles

[](#user-roles)

Turbulence includes a built-in role system with four predefined roles:

```
use ArtisanBuild\Turbulence\Enums\UserRoles;

// Available roles
UserRoles::Owner       // Full control
UserRoles::SuperAdmin  // Can create admins
UserRoles::Admin       // Administrative access
UserRoles::User        // Standard user

// Role permissions
$user->role->canImpersonate();   // true for all except User
$user->role->canCreateAdmin();   // true for Owner and SuperAdmin
```

The installer automatically adds the `role` cast to your User model:

```
protected $casts = [
    'role' => UserRoles::class,
];
```

### Organizational Units

[](#organizational-units)

Organizational units provide a flexible way to model hierarchical structures within accounts:

```
use ArtisanBuild\Turbulence\Models\OrganizationalUnit;

// Extend the base class for your specific units
class Department extends OrganizationalUnit
{
    protected $table = 'organizational_units';

    public function account()
    {
        return $this->belongsTo(Account::class);
    }
}

// Create organizational units
$department = Department::create([
    'account_id' => $account->id,
    'type' => 'department',
]);
```

Account Session Management
--------------------------

[](#account-session-management)

Turbulence provides middleware for managing account context in your application.

### Basic Account Context

[](#basic-account-context)

Add the middleware to routes that need account context:

```
use ArtisanBuild\Turbulence\Middleware\AddAccountSessionToRequest;

Route::middleware([AddAccountSessionToRequest::class])
    ->group(function () {
        // Account is available in the request
        Route::get('/dashboard', function (Request $request) {
            $account = $request->account;
        });
    });
```

### URL-Based Account Switching

[](#url-based-account-switching)

Enable URL-based account context in the configuration:

```
'account_session_urls' => [
    'enabled' => true,
    'index_key' => 'u',  // /u/0/dashboard
    'id_key' => 'i',     // /i/123/dashboard
],
```

Configure routes with account identifiers:

```
Route::middleware([SetDefaultsForAccountSessionUrls::class])
    ->prefix('{account_identifier}')
    ->group(function () {
        // Access via /u/0/dashboard (index-based)
        // or /i/123/dashboard (ID-based for impersonation)
        Route::get('/dashboard', DashboardController::class);
    });
```

The middleware will automatically load the appropriate account based on the URL:

- `/u/0/dashboard` - Loads the first account from `session('accounts')`
- `/i/301319658141229056/dashboard` - Loads account by ID (useful for impersonation)

Usage Examples
--------------

[](#usage-examples)

### Creating an Account for a User

[](#creating-an-account-for-a-user)

```
use App\Models\Account;
use App\Models\AccountProfile;

$account = Account::create([
    'user_id' => $user->id,
]);

// Create the associated profile
AccountProfile::create([
    'account_id' => $account->id,
    'company_name' => 'Acme Corporation',
    'industry' => 'Technology',
]);

// Set as current account
$user->switchAccount($account);
```

### Multi-Account User Flow

[](#multi-account-user-flow)

```
// User with multiple accounts
$user = User::find(1);

// List all accounts
foreach ($user->accounts as $account) {
    echo $account->profile->company_name;
}

// Switch between accounts
$targetAccount = $user->accounts()->where('id', 5)->first();

if ($user->switchAccount($targetAccount)) {
    // Successfully switched
    return redirect()->route('dashboard');
}
```

### Role-Based Authorization

[](#role-based-authorization)

```
use ArtisanBuild\Turbulence\Enums\UserRoles;

// Check roles in controllers
public function impersonate(User $targetUser)
{
    if (!auth()->user()->role->canImpersonate()) {
        abort(403, 'You cannot impersonate users');
    }

    // Proceed with impersonation
}

// Use in blade templates
@if(auth()->user()->role === \ArtisanBuild\Turbulence\Enums\UserRoles::Owner)
    Admin Settings
@endif

// Gate definitions
Gate::define('create-admin', function (User $user) {
    return $user->role->canCreateAdmin();
});
```

### Building Organizational Structures

[](#building-organizational-structures)

```
// Create custom organizational units
class Department extends OrganizationalUnit {}
class Team extends OrganizationalUnit {}
class Project extends OrganizationalUnit {}

// Build your structure
$engineering = Department::create([
    'account_id' => $account->id,
    'type' => 'department',
    'name' => 'Engineering',
]);

$backend = Team::create([
    'account_id' => $account->id,
    'type' => 'team',
    'name' => 'Backend Team',
    'parent_id' => $engineering->id,
]);
```

Development Commands
--------------------

[](#development-commands)

### Code Quality

[](#code-quality)

```
# Fix code style
composer lint

# Run static analysis
composer stan

# Run tests
composer test

# Run all quality checks
composer ready
```

### Testing

[](#testing)

```
# Run tests
composer test

# Run with coverage
composer test-coverage
```

Advanced Usage
--------------

[](#advanced-usage)

### Customizing Models

[](#customizing-models)

You can extend the base models to add custom functionality:

```
// app/Models/Account.php
namespace App\Models;

use ArtisanBuild\Turbulence\Models\Account as BaseAccount;

class Account extends BaseAccount
{
    public function profile()
    {
        return $this->hasOne(AccountProfile::class);
    }

    public function isActive(): bool
    {
        return $this->profile->subscription_status === 'active';
    }
}
```

### Account Session Storage

[](#account-session-storage)

Store account session data for URL-based switching:

```
// Store accounts in session (typically during login)
session(['accounts' => [
    ['id' => 1, 'name' => 'Personal Account'],
    ['id' => 2, 'name' => 'Work Account'],
]]);

// Load from session using AccountSession helper
use ArtisanBuild\Turbulence\Support\AccountSession;

// Load by index (for /u/0/ URLs)
$account = AccountSession::loadFromIndex(0);

// Load by ID (for /i/123/ URLs)
$account = AccountSession::load(123);
```

Roadmap
-------

[](#roadmap)

- `turbulence:generate` command for scaffolding custom organizational units
- Additional relationship helpers for complex organizational structures
- Built-in permission system beyond basic roles
- Account invitation system
- Account transfer functionality

Testing
-------

[](#testing-1)

The package includes a comprehensive test suite using Pest:

```
composer test
```

Contributing
------------

[](#contributing)

Contributions are welcome! Please ensure all tests pass before submitting a pull request:

```
composer ready
```

License
-------

[](#license)

The MIT License (MIT). Please see the LICENSE file for more information.

Credits
-------

[](#credits)

- [Artisan Build](https://github.com/artisan-build)
- [All Contributors](../../contributors)

###  Health Score

20

—

LowBetter than 14% of packages

Maintenance48

Moderate activity, may be stable

Popularity9

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity13

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/55eed7400c452edf7e7adfa4f1c6676b65b5ce1867fff6bddcb80b1bb45360af?d=identicon)[edgrosvenor](/maintainers/edgrosvenor)

---

Top Contributors

[![edgrosvenor](https://avatars.githubusercontent.com/u/1053395?v=4)](https://github.com/edgrosvenor "edgrosvenor (11 commits)")

### Embed Badge

![Health badge](/badges/artisan-build-turbulence/health.svg)

```
[![Health](https://phpackages.com/badges/artisan-build-turbulence/health.svg)](https://phpackages.com/packages/artisan-build-turbulence)
```

###  Alternatives

[letournel/path-finder

Path finder algorithm

142.0k](/packages/letournel-path-finder)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
