bensedev / request-bag
Request-scoped data container for Laravel
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 2
pkg:composer/bensedev/request-bag
Requires
- php: ^8.4
- illuminate/contracts: ^12.0
- illuminate/support: ^12.0
Requires (Dev)
- laravel/framework: ^12.20
- laravel/pint: ^1.0
- nunomaduro/collision: ^v8.1.1
- pestphp/pest: ^v3.0.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.0.0
This package is auto-updated.
Last update: 2025-12-24 10:43:18 UTC
README
A simple, request-scoped data container for Laravel
RequestBag provides an easy way to share data between classes during a single request lifecycle without passing parameters around. Perfect for middleware chains, Inertia.js setups, and any scenario where you need to share contextual data across your application.
Why RequestBag?
- ๐ฏ Request-scoped - Data lives only for the duration of a single request
- ๐ No parameter passing - Share data between classes without cluttering method signatures
- ๐ Type-safe - Built with PHP 8.4+ and strict types
- ๐จ Clean API - Simple, intuitive methods that just work
- ๐งช Fully tested - Comprehensive test coverage with Pest
- โจ Laravel-friendly - Facade support and automatic service provider registration
Installation
Install via Composer:
composer require bensedev/request-bag
The service provider and facade are automatically registered via Laravel's package discovery.
Usage
Basic Usage
use Bensedev\RequestBag\Facades\RequestBag; // Add data RequestBag::add('user_permissions', ['edit', 'delete', 'create']); RequestBag::add('tenant_id', 123); // Retrieve data $permissions = RequestBag::get('user_permissions'); $tenantId = RequestBag::get('tenant_id'); // With default value $theme = RequestBag::get('theme', 'light'); // Check if key exists and has value if (RequestBag::has('user_permissions')) { // Key exists and is not empty } // Check if key exists (even if empty) if (RequestBag::exists('theme')) { // Key exists }
Middleware Example
Share computed data from middleware with your controllers:
namespace App\Http\Middleware; use Bensedev\RequestBag\Facades\RequestBag; use Closure; class LoadUserPermissions { public function handle($request, Closure $next) { $permissions = auth()->user()->permissions->pluck('name')->toArray(); // Store in RequestBag instead of adding to request RequestBag::add('user_permissions', $permissions); RequestBag::add('is_admin', auth()->user()->isAdmin()); return $next($request); } }
Then access it anywhere in your application:
namespace App\Http\Controllers; use Bensedev\RequestBag\Facades\RequestBag; class PostController extends Controller { public function store() { // No need to pass permissions around! if (RequestBag::has('user_permissions')) { $permissions = RequestBag::get('user_permissions'); if (in_array('create_post', $permissions)) { // Create post } } } }
Inertia.js Example
Share data with your Inertia frontend:
namespace App\Http\Middleware; use Bensedev\RequestBag\Facades\RequestBag; use Illuminate\Http\Request; use Inertia\Middleware; class HandleInertiaRequests extends Middleware { public function share(Request $request): array { return array_merge(parent::share($request), [ 'auth' => [ 'user' => $request->user(), // Pull from RequestBag populated earlier in middleware chain 'permissions' => RequestBag::get('user_permissions', []), 'is_admin' => RequestBag::get('is_admin', false), ], 'tenant' => [ 'id' => RequestBag::get('tenant_id'), 'name' => RequestBag::get('tenant_name'), ], ]); } }
Service/Repository Pattern
Share computed data between services:
namespace App\Services; use Bensedev\RequestBag\Facades\RequestBag; class TenantService { public function loadTenantContext(int $tenantId): void { $tenant = Tenant::with('settings')->find($tenantId); RequestBag::merge([ 'tenant_id' => $tenant->id, 'tenant_name' => $tenant->name, 'tenant_settings' => $tenant->settings->toArray(), ]); } } class InvoiceService { public function createInvoice(array $data): Invoice { // Access tenant data without dependency injection $tenantId = RequestBag::get('tenant_id'); $settings = RequestBag::get('tenant_settings'); return Invoice::create([ 'tenant_id' => $tenantId, 'currency' => $settings['default_currency'], // ... ]); } }
API Reference
Adding Data
// Add a single value RequestBag::add(string $key, mixed $value): self // Merge multiple values RequestBag::merge(array $data): self // Example RequestBag::add('user_id', 123); RequestBag::merge(['theme' => 'dark', 'locale' => 'en']);
Retrieving Data
// Get a value (with optional default) RequestBag::get(string $key, mixed $default = null): mixed // Get all data RequestBag::all(): array // Example $userId = RequestBag::get('user_id'); $theme = RequestBag::get('theme', 'light'); $all = RequestBag::all();
Checking Data
// Check if key exists and is not empty RequestBag::has(string $key): bool // Check if key exists (even if empty) RequestBag::exists(string $key): bool // Example if (RequestBag::has('user_id')) { // Key exists and has a value } if (RequestBag::exists('theme')) { // Key exists (might be empty) }
Removing Data
// Remove a specific key RequestBag::remove(string $key): self // Clear all data RequestBag::clear(): self // Example RequestBag::remove('temp_data'); RequestBag::clear();
Method Chaining
All methods that modify the bag return self for fluent chaining:
RequestBag::add('key1', 'value1') ->add('key2', 'value2') ->merge(['key3' => 'value3']) ->remove('key1');
Direct Class Usage
You can also inject the class directly instead of using the facade:
use Bensedev\RequestBag\RequestBag; class MyService { public function __construct( private RequestBag $bag ) {} public function doSomething(): void { $this->bag->add('key', 'value'); } }
Testing
Run the test suite:
composer test
Run PHPStan:
composer analyse
Run Laravel Pint:
composer format
Requirements
- PHP 8.4 or higher
- Laravel 12.0 or higher
License
The MIT License (MIT). Please see License File for more information.
Credits
Support
If you discover any issues, please open an issue on GitHub.