Laravel Tutorials

Efficient Context Management with Laravel's Remember Functions

Published
Efficient Context Management with Laravel's Remember Functions image

Laravel's Context API introduces powerful remember() and rememberHidden() methods that streamline request-scoped data management through elegant closure-based memoization. These functions optimize expensive computations across your application with clean, expressive syntax.

The remember() function provides automatic memoization within the request context:

use Illuminate\Support\Facades\Context;
 
$roles = Context::remember('user-roles', fn() => $this->calculateUserRoles(auth()->user()));

This method automatically manages the existence check and computation cycle, executing the closure only when the context key is absent.

Consider a multi-service architecture where request-scoped data like organization settings, access controls, and feature configurations must be shared efficiently across various application layers. These values are computationally expensive but frequently accessed throughout the request lifecycle:

<?php
 
namespace App\Services;
 
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\DB;
use App\Models\Organization;
use App\Models\User;
 
class OrganizationContextService
{
public function getOrganizationSettings(): array
{
return Context::remember('org-settings', function () {
$organization = $this->getCurrentOrganization();
 
return [
'subscription_tier' => $this->getSubscriptionTier($organization),
'enabled_modules' => $this->getEnabledModules($organization),
'user_limits' => $this->getUserLimits($organization),
'integration_settings' => $this->getIntegrationSettings($organization),
];
});
}
 
public function getCurrentUserAccessLevel(): array
{
return Context::remember('user-access-level', function () {
$user = auth()->user();
$organization = $this->getCurrentOrganization();
 
$directPermissions = $user->permissions()
->where('organization_id', $organization->id)
->pluck('action')
->toArray();
 
$groupPermissions = $user->groups()
->with('permissions')
->get()
->flatMap(fn($group) => $group->permissions)
->pluck('action')
->toArray();
 
$inheritedPermissions = $this->calculateInheritedPermissions($user, $organization);
 
return array_unique(array_merge(
$directPermissions,
$groupPermissions,
$inheritedPermissions
));
});
}
 
public function getSecureCredentials(): array
{
return Context::rememberHidden('secure-credentials', function () {
$organization = $this->getCurrentOrganization();
 
return [
'api_secret' => decrypt($organization->encrypted_api_secret),
'webhook_token' => $this->generateWebhookToken($organization),
'internal_key' => $this->getInternalEncryptionKey($organization),
];
});
}
 
public function hasFeatureAccess(string $feature): bool
{
$settings = $this->getOrganizationSettings();
$userAccess = $this->getCurrentUserAccessLevel();
 
return in_array($feature, $settings['enabled_modules']) &&
in_array("feature:{$feature}", $userAccess);
}
 
protected function getCurrentOrganization(): Organization
{
return Context::remember('current-organization', function () {
$subdomain = request()->route('organization') ?? request()->getHost();
 
return Organization::where('subdomain', $subdomain)
->with(['subscription', 'settings'])
->firstOrFail();
});
}
 
protected function getSubscriptionTier(Organization $organization): string
{
return $organization->subscription->tier ?? 'basic';
}
 
protected function getEnabledModules(Organization $organization): array
{
$baseTier = $this->getSubscriptionTier($organization);
$customModules = $organization->settings->pluck('module')->toArray();
 
return array_merge(
$this->getDefaultModulesForTier($baseTier),
$customModules
);
}
 
protected function getUserLimits(Organization $organization): array
{
$tier = $this->getSubscriptionTier($organization);
 
return match($tier) {
'enterprise' => ['max_users' => -1, 'storage_gb' => 1000],
'professional' => ['max_users' => 100, 'storage_gb' => 100],
'basic' => ['max_users' => 10, 'storage_gb' => 10],
default => ['max_users' => 5, 'storage_gb' => 1],
};
}
 
protected function getIntegrationSettings(Organization $organization): array
{
return $organization->integrations()
->where('active', true)
->get()
->mapWithKeys(fn($integration) => [
$integration->service => $integration->configuration
])
->toArray();
}
 
protected function calculateInheritedPermissions(User $user, Organization $organization): array
{
if ($user->is_organization_owner) {
return ['admin:*', 'user:*', 'billing:*', 'settings:*'];
}
 
if ($user->is_manager) {
return ['user:manage', 'reports:view', 'settings:view'];
}
 
return ['profile:edit', 'dashboard:view'];
}
 
protected function generateWebhookToken(Organization $organization): string
{
return hash_hmac('sha256', $organization->id . now()->timestamp, config('app.key'));
}
 
protected function getInternalEncryptionKey(Organization $organization): string
{
return hash('sha256', config('app.key') . $organization->uuid);
}
 
protected function getDefaultModulesForTier(string $tier): array
{
return match($tier) {
'enterprise' => ['analytics', 'integrations', 'advanced_reports', 'api_access'],
'professional' => ['analytics', 'basic_reports', 'limited_api'],
'basic' => ['dashboard', 'basic_reports'],
default => ['dashboard'],
};
}
}
 
class ReportingController extends Controller
{
public function __construct(
private OrganizationContextService $contextService
) {}
 
public function generateReport(Request $request)
{
if (!$this->contextService->hasFeatureAccess('advanced_reports')) {
abort(403, 'Advanced reporting not available for current plan');
}
 
$settings = $this->contextService->getOrganizationSettings();
$userAccess = $this->contextService->getCurrentUserAccessLevel();
 
return view('reports.advanced', compact('settings', 'userAccess'));
}
 
public function exportData(Request $request)
{
$credentials = $this->contextService->getSecureCredentials();
 
if (!$this->verifyExportPermissions($credentials['internal_key'])) {
abort(401, 'Invalid export permissions');
}
 
return $this->processDataExport($request);
}
}

The remember() function ensures expensive operations like permission calculations and organization lookups execute only once per request, regardless of access frequency. The rememberHidden() variant maintains identical caching behavior while excluding sensitive data from log entries, making it ideal for credentials and security tokens.

This pattern excels in middleware layers, service dependencies, and view composers where identical context data requires multiple access points. The closure-based design creates self-documenting code that clearly indicates the computation triggered during cache misses.

Harris Raftopoulos photo

Senior Software Engineer • Staff & Educator @ Laravel News • Co-organizer @ Laravel Greece Meetup

Sponsored

laravelcloud logo
Laravel Cloud

Easily create and manage your servers and deploy your Laravel applications in seconds.

Visit Laravel Cloud

The latest

View all →
Agent Run Observability in Laravel AI SDK 0.11 image

Agent Run Observability in Laravel AI SDK 0.11

Read article
Debounced Queued Event Listeners in Laravel image

Debounced Queued Event Listeners in Laravel

Read article
Statamic Mailables Viewer Previews Laravel Emails in the Control Panel image

Statamic Mailables Viewer Previews Laravel Emails in the Control Panel

Read article
Laravel Tackle: Run an AI Coding Agent in Your Laravel App image

Laravel Tackle: Run an AI Coding Agent in Your Laravel App

Read article
Queue::forward(): Reroute Laravel Queues in One Place image

Queue::forward(): Reroute Laravel Queues in One Place

Read article
Laravel Read-Through Filesystem: Lazy Storage Migration image

Laravel Read-Through Filesystem: Lazy Storage Migration

Read article