The MaatifyException base class allows developers to override default metadata (HTTP Status, Error Code) but enforces strict guardrails.
You cannot override the category of an exception.
ValidationMaatifyExceptionwill always beVALIDATION.SystemMaatifyExceptionwill always beSYSTEM.
This prevents "Taxonomy Drift" where exceptions lose their semantic meaning.
If you provide an $errorCodeOverride in the constructor:
- The code must exist in the
ALLOWED_ERROR_CODESmapping for that category. - If it does not match, a
LogicExceptionis thrown immediately.
The default policy validation is permissive for unconfigured categories:
- Unconfigured category: Allows all codes.
- Configured category with empty list: Allows all codes.
- Configured category with codes: Strictly enforces the allowed list.
Example:
ValidationMaatifyExceptionallowsINVALID_ARGUMENT.- It forbids
DATABASE_CONNECTION_FAILED.
(Note: Since ValidationMaatifyException is abstract, these rules apply to any concrete class extending it.)
If you provide an $httpStatusOverride:
- It must match the default status class (Client Error vs Server Error).
4xxdefaults can be overridden with other4xxcodes.5xxdefaults can be overridden with other5xxcodes.- Cross-class overrides are forbidden. (e.g., 400 -> 500).
This ensures that a client-side error (Validation) never accidentally reports a server-side failure (System) to monitoring tools.
You can inject a custom ErrorPolicyInterface to override default rules (e.g., allow extra codes).
// Create a policy with custom rules
$customPolicy = DefaultErrorPolicy::withOverrides(
allowedOverrides: ['VALIDATION' => ['MY_CUSTOM_CODE']]
);
// Inject globally (PROCESS-WIDE)
MaatifyException::setGlobalPolicy($customPolicy);
MaatifyException::setGlobalEscalationPolicy($customEscalationPolicy);The library resolves policies in the following order:
- Escalated: (Highest Priority) Logic derived from previous exception wrapping.
- Override: Instance-specific overrides passed to the constructor.
- Default: The active
ErrorPolicyInterface(Global or Default).
In persistent environments (e.g., Swoole, RoadRunner), static global state persists across requests. Global policy setters (setGlobalPolicy, setGlobalEscalationPolicy) are PROCESS-WIDE.
- Risk: Setting a global policy in one request may affect subsequent requests.
- Best Practice: Set global policies only during application bootstrap, before handling any requests.
- Cleanup: Use
MaatifyException::resetGlobalPolicies()to clear all static overrides.