Appearance
Config Registry System
Flow ID: SY-19 | Module(s): core | Complexity: Medium Last Updated: 2026-04-04
Business Overview
The Registry is the platform's database-backed configuration system. It stores key-value pairs organized by group, with optional language scoping and encryption support. Nearly every aspect of the platform's runtime behavior is configured through the Registry -- from email subjects and payment provider credentials to feature flags and integration API keys.
What the Registry provides:
- Hierarchical configuration: group -> key -> language -> value
- Language-scoped settings for multilingual sites
- Encrypted value support for sensitive data (API keys, secrets)
- PSCache integration for read performance
- Method chaining for fluent API usage
- Array serialization (pipe-delimited) for list values
Why it matters: The Registry is referenced by virtually every module in the platform. Understanding its structure is essential for debugging, configuration, and client customization.
Architecture
Registry (Library)
|
+--> constructor:
| load Registry_model
| load PSCache
| load Encryption
| parseDb( pscache->model('registry_model', 'all', []) )
|
+--> value($group, $key, $lang, $encrypted)
| read from in-memory $data[$group][$key][$lang]
| optional decrypt via Encryption library
|
+--> setValue($group, $key, $val, $lang, $encrypted)
| update in-memory cache
| persist via Registry_model::set_regval()
|
+--> live()
refresh PSCache + re-parse from DB
(used by jobs that need latest config)Core Classes
| Class | File | Purpose |
|---|---|---|
Registry | application/libraries/Registry.php | Main library (loaded globally) |
Registry_model | application/models/Registry_model.php | Database access layer |
Access Pattern
The Registry is loaded as a CI library and available throughout the application:
php
// Read a value
$this->registry->value('EMAIL_SUBJECTS', 'ORDER_UPDATE', 'el');
// Read without language (BASE)
$this->registry->value('PAY_BY_BANK', 'API_KEY');
// Read encrypted value
$this->registry->value('PAY_BY_BANK', 'API_KEY', '', true);
// Read as array (pipe-delimited)
$this->registry->getArray('AVAILABLE_COUNTRIES', 'ESHOP');
// Read entire group as associative array
$this->registry->getGroupAsArray('COMPANY', '', ['API_SECRET']);
// Write a value
$this->registry->setValue('COMPANY', 'PHONE', '2101234567');
// Write array (pipe-delimited serialization)
$this->registry->setArray('AVAILABLE_COUNTRIES', 'ESHOP', '', ['GR', 'CY', 'DE']);
// Delete a value
$this->registry->delete('OLD_GROUP', 'DEPRECATED_KEY');
// Refresh from database (for jobs)
$this->registry->live();Code Flow
1. Initialization (Constructor)
- Load
Registry_modelandpscache,encryptionlibraries - Fetch all registry rows via PSCache:
pscache->model('registry_model', 'all', []) - Parse into a 3-level associative array:
$data[group][key][lang] = value - Empty
langvalues are stored under theBASEconstant
2. Reading Values
value($regGroup, $regKey, $langAbbr, $encrypted):
- If
$langAbbris empty, usesBASE(language-independent) - Looks up
$data[$regGroup][$regKey][strtoupper($langAbbr)] - If
$encryptedis true, decrypts the value via the Encryption library - Returns
nullif not found
3. Writing Values
setValue($regGroup, $regKey, $regVal, $langAbbr, $encrypted):
- Updates the in-memory cache
- Calls
Registry_model::set_regval()which performs an upsert:- If a matching row exists (group + key + lang), updates
regval - If not, inserts a new row
- If a matching row exists (group + key + lang), updates
- If
$encryptedis true, the model encrypts the value before storage
4. Live Refresh
live():
- Called by background jobs to ensure they have the latest config
- Forces PSCache to refresh:
pscache->updateCache('registry_model', 'all', []) - Re-parses the database data into memory
- Returns
$thisfor method chaining
5. Array Values
getArray($regKey, $regGroup, $langAbbr, $encrypted):
- Reads the value and explodes by
|delimiter - Returns an array of strings
setArray($regKey, $regGroup, $langAbbr, $regVal, $encrypted):
- Implodes the array by
|delimiter and stores as a single string
Data Model
Table: registry
| Column | Type | Role |
|---|---|---|
reggroup | varchar | Configuration group (e.g., EMAIL_SUBJECTS, PAY_BY_BANK, ESHOP) |
regkey | varchar | Configuration key within the group |
regval | text | Configuration value (plain text or encrypted) |
lang | varchar | Language code (empty string = language-independent) |
Composite key behavior: The combination of reggroup + regkey + lang acts as a unique identifier. The set_regval() method performs an upsert on this combination.
Common Registry Groups
| Group | Purpose | Example Keys |
|---|---|---|
EMAIL_SUBJECTS | Email subject templates | ORDER_UPDATE, WAITING_LIST, CUSTOMER_INFORM_DELAY |
EMAIL_SHOP_MAILER | SMTP configuration | SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS |
ESHOP | General e-shop settings | AVAILABLE_COUNTRIES, DEFAULT_CURRENCY |
PAY_BY_BANK | PayByBank configuration | API_KEY, API_URL, EXPIRATION |
COMPANY | Company information | PHONE, EMAIL, NAME |
SEO | SEO settings | META_TITLE, META_DESCRIPTION |
SOCIAL | Social media links | FACEBOOK, INSTAGRAM, TWITTER |
Configuration
Loading
The Registry is auto-loaded as a CI library. It is available via:
$this->registryin controllers and modelsregistry()helper function (if the helper is loaded)
Caching
- PSCache layer: Registry data is cached via PSCache (file or Redis-based). Cache is keyed on
registry_model::all - In-memory: After loading, all values are held in the
$dataarray for the duration of the request - Refresh:
live()method forces a cache refresh -- used by cron jobs and long-running processes
Encryption
- Uses CI's
Encryptionlibrary for sensitive values - Encrypted values are stored as ciphertext in the database
- Decryption happens at read time when
$encrypted=trueis passed - The
getGroupAsArray()method accepts an$encryptedKeysarray to decrypt specific keys within a group
Client Extension Points
Add custom registry entries: Insert rows into the
registrytable directly or via the admin settings interface. No code changes needed for simple key-value configuration.Override the Registry library: Create
application/libraries/Registry.phpextending the base class to add custom methods (e.g., typed getters, validation).Override the Registry model: Create
application/models/Registry_model.phpto customize database queries (e.g., add audit logging on writes).Admin Settings UI: The admin settings page (AD-13) provides a UI for managing many registry groups. Client-specific settings can be added to the settings views.
Patchers for data migration: Use the
AbstractPatchermechanism to create registry entries during deployment (e.g., set initial values for new features).
Business Rules
| Rule | Description |
|---|---|
| Language fallback | No automatic fallback -- if a language-specific value is not found, null is returned. Callers must handle fallback logic |
| BASE language | Empty language string maps to BASE constant internally |
| Upsert semantics | setValue() creates or updates -- no separate create/update methods |
| Pipe-delimited arrays | Array values are stored as pipe-delimited strings (e.g., GR|CY|DE) |
| Encryption at rest | Sensitive values can be encrypted in the database; decrypted on read |
| Cache coherence | Background jobs must call live() to get fresh values; web requests use PSCache TTL |
| Universal dependency | The Registry is used by virtually every module -- changing its structure has platform-wide impact |
Related Flows
- AD-13 Settings -- admin UI for managing registry values
- AD-37 Metadata / Registry System -- admin-focused documentation of the Registry (well-known groups, product metadata)
- SY-01 Cron Job Framework -- jobs call
registry->live()for fresh config - SY-16 PayByBank Polling -- example of registry-configured integration
Wiki Guide: Settings in Database -- developer guide for database-backed configuration