Installation
Run composer require effiana/config-bundle:~2.2 in your Symfony project root.
Ensure your AppKernel.php includes:
new Effiana\ConfigBundle\EffianaConfigBundle(),
Database Setup Create the required table via migrations:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
(Alternative: php bin/console doctrine:schema:update --force)
First Configuration
Define a config key in config.yml (or via CLI):
php bin/console effiana:config:add my_app.max_upload_size 10M
Retrieve it in a service/controller:
$maxSize = $this->get('effiana_config.config')->get('my_app.max_upload_size');
Optional Admin UI
Import routes in routing.yml:
effiana_config_settings:
resource: "@EffianaConfigBundle/Resources/config/routing/settings.xml"
prefix: /admin
Access /admin/settings to manage configs via a basic UI.
Service Integration
Inject the effiana_config.config service (alias: effiana_config) anywhere:
use Effiana\ConfigBundle\Service\ConfigService;
class MyService {
public function __construct(private ConfigService $config) {}
}
get(string $key, mixed $default = null) for retrieval.set(string $key, mixed $value) for updates (requires admin privileges in most cases).Environment-Specific Configs Override defaults per environment by prefixing keys:
# config_dev.yml
parameters:
effiana_config.prefixes: ['dev_']
Then store configs like dev_my_app.debug_mode: true.
Validation & Defaults
Define validation rules in config.yml:
effiana_config:
validation:
my_app.max_upload_size: "numeric"
my_app.enabled_features: "array"
Provide defaults via CLI or migrations:
php bin/console effiana:config:set my_app.timeout 30 --default
Event-Driven Updates Listen for config changes via events:
// src/Acme/EventListener/ConfigListener.php
class ConfigListener {
public function onConfigUpdate(ConfigUpdateEvent $event) {
if ($event->getKey() === 'my_app.cache_enabled') {
$this->cacheManager->invalidateAll();
}
}
}
Register in services.yml:
services:
Acme\EventListener\ConfigListener:
tags:
- { name: 'kernel.event_listener', event: 'effiana.config.update' }
Caching Layer Enable caching for performance (default: disabled):
effiana_config:
cache: true
cache_lifetime: 3600 # 1 hour
Clear cache manually when needed:
php bin/console cache:clear effiana_config
$form = $this->createFormBuilder()
->add('maxUploadSize', TextType::class, [
'data' => $this->config->get('my_app.max_upload_size'),
])
->getForm();
$this->logger->info('Config updated', [
'key' => $key,
'old_value' => $oldValue,
'new_value' => $newValue,
]);
$entityManager->getFilters()->enable('softdelete')
if ($this->config->get('app.soft_delete_enabled'));
Case Sensitivity
Config keys are case-sensitive. MY_APP.KEY ≠ my_app.key.
Tip: Use a naming convention (e.g., snake_case) consistently.
Migration Conflicts If the table already exists, migrations may fail. Manually check:
php bin/console doctrine:schema:update --dump-sql
Tip: Use --complete flag if needed:
php bin/console doctrine:schema:update --complete
Caching Quirks
php bin/console cache:clear effiana_config
Tip: Disable caching in dev environment for debugging.
Permission Issues
The default UI requires ROLE_ADMIN. Customize security in security.yml:
access_control:
- { path: ^/admin/settings, roles: [CONFIG_EDITOR] }
Tip: Create a dedicated role for config editors.
Serialization Limits
Complex objects (e.g., DateTime, custom classes) won’t serialize by default.
Workaround: Store strings/JSON and cast manually:
$date = new \DateTime($this->config->get('app.last_updated'));
Event Ordering Events fire after the config is updated. For pre-update logic, use a subscriber:
class ConfigSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
'effiana.config.pre_update' => 'onPreUpdate',
];
}
}
Dump All Configs Use the debug command:
php bin/console effiana:config:list
Tip: Filter by prefix:
php bin/console effiana:config:list --prefix="app."
Check Database
Inspect the config table directly:
SELECT * FROM config WHERE `key` LIKE 'my_app.%';
Enable Debug Mode
Set in config.yml:
effiana_config:
debug: true
Logs config operations to dev.log.
Override Configs Temporarily
Use the parameters override in config_dev.yml:
parameters:
effiana_config.overrides:
my_app.debug_mode: true
Custom Storage
Implement Effiana\ConfigBundle\Storage\ConfigStorageInterface for non-DB backends (e.g., Redis):
class RedisConfigStorage implements ConfigStorageInterface {
public function get($key) { /* ... */ }
public function set($key, $value) { /* ... */ }
// ...
}
Register in services.yml:
effiana_config.storage: '@my.redis_config_storage'
Custom Validation Extend the validator:
class CustomValidator extends \Effiana\ConfigBundle\Validator\ConfigValidator {
public function validate($value, Constraint $constraint) {
if ($constraint->getName() === 'is_even') {
return $value % 2 === 0;
}
return parent::validate($value, $constraint);
}
}
Update services.yml:
effiana_config.validator: '@my.custom_validator'
Custom UI
Override the default Twig templates in Resources/views/:
app/Resources/EffianaConfigBundle/views/
Settings/
index.html.twig
edit.html.twig
Tip: Extend the base template:
{% extends '@EffianaConfig/settings/index.html.twig' %}
{% block settings_table %}
{{ parent() }}
<tr><td>Custom Field</td><td>{{ config.get('custom.key') }}</td></tr>
{% endblock %}
How can I help you explore Laravel packages today?