feat: Add namespaced get/set API to AppContext (with deprecation for dynamic properties) #3429
+819
−186
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What does this implement/fix? Explain your changes.
This PR implements a formal, namespaced API for storing and retrieving data in the
AppContextclass while maintaining full backward compatibility with existing dynamic property usage.New API Methods
Adds six new methods to
AppContextfor managing request-scoped state with namespace isolation:set(string $namespace, string $key, $value): void- Store a valueget(string $namespace, string $key, $default = null): mixed- Retrieve a value with optional defaulthas(string $namespace, string $key): bool- Check if a key existsremove(string $namespace, string $key): void- Remove a specific keyclear(string $namespace): void- Clear all data in a namespaceall(string $namespace): array- Get all data in a namespaceImplementation Details
$storeproperty as nested arrays ($store[$namespace][$key]) to prevent collisions between plugins/extensions__set()magic method that triggers_doing_it_wrong()when setting dynamic properties (not existing properties)Testing
AppContextfunctionality to ensure no regressionsCode Quality
get_loader()method@phpstan-ignorecomments across the codebasephpcs:ignorecomments for semantic parameter names ($namespace,$default)Does this close any currently open issues?
Closes #3393
Any other comments?
Why Namespace Isolation?
Without namespaces, different plugins could accidentally overwrite each other's context data. By requiring a namespace (recommended to use plugin text domain), we ensure:
Migration Path
Existing code using dynamic properties will continue to work but will see deprecation notices in debug mode:
Use Cases
This API is perfect for request-scoped state management patterns, including, but not limited to:
🌍 Internationalization (i18n)
Store user's preferred locale, language settings, or translation context to localize GraphQL responses on a per-request basis.
🧪 A/B Testing & Feature Flags
Determine variant assignments or feature flags at the request start, then use consistently across all resolvers in that request.
🔒 Private/Protected Content Access
Store password verification state or content access tokens to avoid re-checking permissions for every field.
👤 User Preferences & Personalization
Cache user preferences fetched once, then reuse across multiple resolvers without repeated database queries.
🔐 External API Authentication
Store API tokens or authentication state for third-party services used during the request.
📊 Request Tracing & Debugging
Add trace IDs, performance markers, or debug context for logging and monitoring.
🏢 Multi-tenancy
Store tenant-specific context, database connections, or configuration for multi-tenant applications.
⚡ Custom Caching Strategies
Store cache keys, bust flags, or other cache-related state specific to the request.
What This API is NOT For:
Example Usage
This pattern ensures: