CMS Framework - v2.2.2
Exception Hierarchy
The CMS Framework uses a structured exception hierarchy to provide consistent error handling throughout the application.
Base Exception
All framework exceptions extend from CMSFrameworkException:
use ArtisanPackUI\CMSFramework\Exceptions\CMSFrameworkException;
try {
// Framework code
} catch (CMSFrameworkException $e) {
// Catch any framework exception
}
Standardized JSON Rendering (v1.1.0)
All framework exceptions automatically render as JSON when the request expects JSON (API requests). Each exception defines an $errorCode and $statusCode:
{
"error": {
"code": "SERVER_ERROR",
"message": "Something went wrong."
}
}
| Exception | Error Code | HTTP Status |
|---|---|---|
CMSFrameworkException |
SERVER_ERROR |
500 |
NotFoundException |
NOT_FOUND |
404 |
UnauthorizedException |
FORBIDDEN |
403 |
ValidationException |
VALIDATION_ERROR |
422 |
See api/Error Responses for complete error response documentation.
Common Exceptions
ValidationException
Thrown when validation fails for user input or data.
use ArtisanPackUI\CMSFramework\Exceptions\ValidationException;
throw ValidationException::withErrors('Validation failed', [
'title' => ['The title field is required.'],
'email' => ['The email must be a valid email address.'],
]);
// Access validation errors
try {
// Code that might throw validation exception
} catch (ValidationException $e) {
$errors = $e->getErrors();
if ($e->hasError('title')) {
// Handle title error
}
}
NotFoundException
Thrown when a requested resource cannot be found.
use ArtisanPackUI\CMSFramework\Exceptions\NotFoundException;
// For models
throw NotFoundException::model(Post::class, $id);
// For generic resources
throw NotFoundException::resource('Theme', 'dark-mode');
UnauthorizedException
Thrown when a user attempts to perform an action they're not authorized for.
use ArtisanPackUI\CMSFramework\Exceptions\UnauthorizedException;
// For actions
throw UnauthorizedException::forAction('delete posts');
// For resources
throw UnauthorizedException::forResource('Post', 'delete');
// For permissions
throw UnauthorizedException::requiresPermission('manage-content');
Module-Specific Exceptions
Core Updates Module
UpdateException - Thrown during update operations
use ArtisanPackUI\CMSFramework\Modules\Core\Updates\Exceptions\UpdateException;
throw UpdateException::versionCheckFailed('Network timeout');
throw UpdateException::downloadFailed($url);
throw UpdateException::backupFailed($path);
throw UpdateException::rollbackFailed($reason);
Plugins Module
PluginInstallationException - Thrown during plugin installation
use ArtisanPackUI\CMSFramework\Modules\Plugins\Exceptions\PluginInstallationException;
throw PluginInstallationException::extractionFailed($slug);
throw PluginInstallationException::alreadyInstalled($slug);
PluginNotFoundException - Thrown when a plugin is not found
use ArtisanPackUI\CMSFramework\Modules\Plugins\Exceptions\PluginNotFoundException;
throw new PluginNotFoundException("Plugin '{$slug}' not found.");
PluginValidationException - Thrown when plugin validation fails
use ArtisanPackUI\CMSFramework\Modules\Plugins\Exceptions\PluginValidationException;
throw new PluginValidationException("Invalid plugin manifest.");
PluginUpdateException - Thrown during plugin updates
use ArtisanPackUI\CMSFramework\Modules\Plugins\Exceptions\PluginUpdateException;
throw new PluginUpdateException("Update failed for plugin '{$slug}'.");
Themes Module
ThemeNotFoundException - Thrown when a theme is not found
use ArtisanPackUI\CMSFramework\Modules\Themes\Exceptions\ThemeNotFoundException;
throw new ThemeNotFoundException("Theme '{$slug}' not found.");
Exception Hierarchy Tree
Exception (PHP)
└── CMSFrameworkException
├── ValidationException
├── NotFoundException
├── UnauthorizedException
└── Module Exceptions
├── UpdateException (Core/Updates)
├── PluginInstallationException (Plugins)
├── PluginNotFoundException (Plugins)
├── PluginValidationException (Plugins)
├── PluginUpdateException (Plugins)
└── ThemeNotFoundException (Themes)
Best Practices
1. Use Specific Exceptions
Always throw the most specific exception available:
// Good - specific exception
throw NotFoundException::model(User::class, $id);
// Bad - generic exception
throw new CMSFrameworkException("User not found");
2. Provide Context
Include relevant context in exception messages:
// Good - includes context
throw UpdateException::downloadFailed("https://example.com/update.zip");
// Bad - vague message
throw new UpdateException("Download failed");
3. Use Static Factory Methods
Leverage static factory methods for consistency:
// Good - using factory method
throw ValidationException::withErrors('Invalid input', $errors);
// Less ideal - direct instantiation
$e = new ValidationException('Invalid input');
$e->errors = $errors;
throw $e;
4. Catch Specific Exceptions
Catch the most specific exception type when possible:
// Good - specific catch
try {
$manager->sendNotification($key, $userIds);
} catch (NotFoundException $e) {
// Handle not found case
} catch (ValidationException $e) {
// Handle validation errors
} catch (CMSFrameworkException $e) {
// Handle other framework exceptions
}
5. Document Thrown Exceptions
Always document which exceptions a method might throw:
/**
* Send a notification to users.
*
* @throws NotFoundException If the notification key is not registered.
* @throws ValidationException If the user IDs are invalid.
* @throws UnauthorizedException If the user lacks permission.
*/
public function sendNotification(string $key, array $userIds): Notification
{
// ...
}
Creating Custom Exceptions
When creating module-specific exceptions, extend from CMSFrameworkException:
<?php
declare( strict_types = 1 );
namespace ArtisanPackUI\CMSFramework\Modules\YourModule\Exceptions;
use ArtisanPackUI\CMSFramework\Exceptions\CMSFrameworkException;
class YourModuleException extends CMSFrameworkException
{
public static function operationFailed(string $operation): self
{
return new self("Operation failed: {$operation}");
}
}
Exception Handling in Controllers
Since v1.1.0, all CMS Framework exceptions automatically render as JSON when the request expects JSON. You no longer need to manually catch exceptions to format error responses — simply let the exception propagate:
public function update(Request $request, int $id)
{
// Exceptions auto-render as standardized JSON responses.
// NotFoundException → 404, UnauthorizedException → 403, etc.
$post = $this->manager->update($id, $request->all());
return response()->json($post);
}
If you need custom handling, you can still catch exceptions:
use ArtisanPackUI\CMSFramework\Exceptions\NotFoundException;
use ArtisanPackUI\CMSFramework\Exceptions\UnauthorizedException;
use ArtisanPackUI\CMSFramework\Exceptions\ValidationException;
public function update(Request $request, int $id)
{
try {
$post = $this->manager->update($id, $request->all());
return response()->json($post);
} catch (NotFoundException $e) {
// Custom handling — the auto-rendered JSON is available via:
// $e->getErrorCode() → 'NOT_FOUND'
// $e->getStatusCode() → 404
}
}