Table of Contents
Component Options Handler Documentation
Handler Method Parameters
When component options are changed, your handler method receives four parameters:
Parameter | Type | Description |
---|---|---|
$component | string | Name of the component (e.g., 'com_yourcomponent') |
$changes | array | Associative array of changed options |
$oldOptions | object | Complete set of component options before changes |
$newOptions | object | Complete set of component options after changes |
The $changes Array Structure
The $changes
array provides a detailed look at which options have been modified. Each key in the array corresponds to an option name, and the value is an associative array containing both the old and new values.
$changes = [ 'option_name' => [ 'old' => 'previous_value', 'new' => 'new_value' ], // Additional changed options follow the same pattern ];
This structure makes it easy to:
- Check if a specific option has changed
- Access both the previous and new values for comparison
- Process only the options that have actually changed
Handling Option Changes
1. Basic Option Check
The simplest approach is to check if a specific option exists in the changes array:
if (isset($changes['cache_lifetime'])) { // The cache_lifetime option has changed $newLifetime = $changes['cache_lifetime']['new']; $oldLifetime = $changes['cache_lifetime']['old']; // Take appropriate action based on the change }
2. Type-Specific Handling
Options can be of various types, and you may need different handling for each:
// Boolean option (checkbox) if (isset($changes['enable_feature'])) { $isEnabled = (bool) $changes['enable_feature']['new']; if ($isEnabled) { // Feature was enabled - initialize required resources } else { // Feature was disabled - clean up resources } } // Numeric option if (isset($changes['items_per_page'])) { $newValue = (int) $changes['items_per_page']['new']; // Validate the new value if ($newValue < 1) { // Log invalid setting } else { // Apply the new setting } } // Text option if (isset($changes['api_key'])) { $newApiKey = $changes['api_key']['new']; if (empty($newApiKey)) { // API key was removed - disable API functionality } else { // New API key - validate and initialize API connection } }
3. Multiple Related Options
Sometimes multiple related options change together and should be handled as a group:
// Check for any changes to email settings $emailSettingsChanged = false; $emailSettings = ['email_from', 'email_sender_name', 'email_template']; foreach ($emailSettings as $setting) { if (isset($changes[$setting])) { $emailSettingsChanged = true; break; } } if ($emailSettingsChanged) { // Get the complete set of current email settings from $newOptions $currentEmailFrom = $newOptions->email_from ?? ''; $currentSenderName = $newOptions->email_sender_name ?? ''; $currentTemplate = $newOptions->email_template ?? 'default'; // Reinitialize email system with new settings $this->initializeEmailSystem($currentEmailFrom, $currentSenderName, $currentTemplate); }
4. Working with Complex Options
For more complex options stored as JSON or serialized data:
if (isset($changes['advanced_settings'])) { $newSettings = $changes['advanced_settings']['new']; // If the setting is stored as JSON string, decode it if (is_string($newSettings)) { $newSettings = json_decode($newSettings); } // Now you can access individual properties if (isset($newSettings->timeout)) { // Handle timeout setting change } }
5. Checking for Option Removal
The $changes
array also tracks options that have been completely removed:
if (isset($changes['legacy_feature']) && $changes['legacy_feature']['new'] === null) { // The option has been completely removed // Perform any cleanup necessary }
Using the Complete Options Objects
While the $changes
array focuses only on what's changed, the $oldOptions
and $newOptions
parameters provide the full context:
// Check if a critical dependency setting has changed if (isset($changes['external_service'])) { // The external service setting changed $newService = $changes['external_service']['new']; // Check related settings that might need to be adjusted $serviceUrl = $newOptions->service_url ?? ''; $serviceKey = $newOptions->service_key ?? ''; // Validate the combination of settings if ($newService === 'enabled' && (empty($serviceUrl) || empty($serviceKey))) { // Log warning - service enabled but required settings are missing Log::add( 'External service enabled but URL or API key is missing', Log::WARNING, 'com_yourcomponent' ); } }
Best Practices
- Validate New Values: Always validate the new option values before using them.
- Type Casting: Cast values to the appropriate type (
(int)
,(bool)
, etc.) before using them. - Handle Gracefully: Use default values and null coalescing (
??
) to handle missing options. - Limit Side Effects: Keep handlers focused on processing only what's needed for the changed options.
- Error Handling: Wrap operations in try/catch blocks to prevent failures from affecting the user experience.
- Logging: Log significant changes and any issues that arise.
- Performance: For performance-critical components, consider using the changes array to process only what's changed rather than reinitializing everything.
Example Implementation
public static function handleOptionsChange($component, $changes, $oldOptions, $newOptions) { // Verify this is our component if ($component !== 'com_yourcomponent') { return; } try { // Process configuration sections based on what changed // 1. Cache settings if (isset($changes['cache_enabled']) || isset($changes['cache_lifetime'])) { self::handleCacheChanges($newOptions); } // 2. API settings if (isset($changes['api_key']) || isset($changes['api_endpoint'])) { self::handleApiChanges($changes, $newOptions); } // 3. General settings that require full refresh $refreshTriggers = ['items_per_page', 'sort_direction', 'default_view']; $needsRefresh = false; foreach ($refreshTriggers as $option) { if (isset($changes[$option])) { $needsRefresh = true; break; } } if ($needsRefresh) { self::refreshComponentState($newOptions); } // Log successful processing Log::add( sprintf('Successfully processed %d option changes', count($changes)), Log::INFO, 'com_yourcomponent' ); } catch (\Exception $e) { // Log error but don't prevent options from being saved Log::add( sprintf('Error processing option changes: %s', $e->getMessage()), Log::ERROR, 'com_yourcomponent' ); } }