Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
294 changes: 215 additions & 79 deletions developer_manual/digging_deeper/config/appconfig.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,36 @@ AppConfig

.. versionadded:: 29

Since v29, Nextcloud includes a new API to manage your app configuration.
Nextcloud includes an AppConfig API to manage app configuration values.

Concept overview
----------------

Nextcloud provides an API to store and access app configuration values.
In addition to simple read/write operations, ``IAppConfig`` supports:

- typed values,
- lazy loading,
- sensitive values,
- key and value discovery helpers.

.. _appconfig_concepts:

.. note::
See `Lexicon Concepts`_ to learn more about **Lexicon**, a way to define configuration keys and avoid conflicts in your code.

.. _Lexicon Concepts: https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/config/lexicon.html#concept-overview


AppFramework
------------

The AppConfig API is also available in the AppFramework, allowing you to use it in your app.
All of the methods are available in the ``OCP\AppFramework\Services\IAppConfig`` interface.
Any of the methods below will automatically be scoped to your app, meaning you can omit the app id.

The AppConfig API is also available in AppFramework through
``OCP\AppFramework\Services\IAppConfig``.

All methods from that interface are scoped to your app automatically, so you do not
need to pass an app ID explicitly.

.. code-block:: php

<?php
Expand All @@ -27,159 +48,274 @@ Any of the methods below will automatically be scoped to your app, meaning you c
private IAppConfig $appConfig,
) {}

public function getSomeConfig(): string {
return $this->appConfig->getAppValueString('mykey', 'default');
public function hasConfig(): bool {
return $this->appConfig->hasAppKey('mykey');
}
}

Concept overview
----------------
Use ``\OCP\IAppConfig`` when you need to read or write configuration for arbitrary app IDs.
Use ``OCP\AppFramework\Services\IAppConfig`` for app-scoped operations in your own app.

Nextcloud includes an API to store and access your app configuration values.
On top of storing and accessing your configuration values, ``IAppConfig`` comes with different concepts:

.. _appconfig_concepts:
Typed config values
^^^^^^^^^^^^^^^^^^^

To improve safety and stability, config values are type-enforced.

A type is set when the key is created in the database and cannot be changed later.

A key’s type is defined by the setter you use when the key is first created
(for example, ``setValueString()`` creates a string key, ``setValueInt()`` an int key).

.. code-block:: php

$appConfig->setValueInt('myapp', 'retry_count', 3); // key type: int
$appConfig->setValueString('myapp', 'display_name', 'A'); // key type: string

.. note::
See `Lexicon Concepts`_ to learn more about **Lexicon**, a way to fully define your configuration keys and avoid conflict when using it in your code.
- Values stored before Nextcloud 29 are treated as ``mixed``.
- It is not possible to manually create new ``mixed`` values.
- Values that are not ``mixed`` must be retrieved using the matching typed getter.

.. _Lexicon Concepts: https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/config/lexicon.html#concept-overview
.. note::
Migration urgency differs between reads and writes:

- Read paths should usually be migrated early to typed getters when adopting
``IAppConfig``, so runtime behavior is explicit and type-safe.
- Write-side normalization of legacy values can often be incremental and done
when touching related code paths, especially if:

- you want stricter typing guarantees,
- you are already refactoring,
- the key is causing ambiguity/bugs

Typed Config Values
^^^^^^^^^^^^^^^^^^^
For new keys, always use typed setters and typed getters.

To ensure better stability of your code, config values are typed enforced.
Type is set only once, at creation in database, and cannot be changed.
**A safe write-side migration pattern is:**

.. note::
- Value stored before Nextcloud 29 are automatically typed as `mixed`. However, it is not possible to manually set a value as `mixed`.
- Value not set as `mixed` must be retrieved using the corresponding method.
#. Read the existing legacy value.
#. Validate/convert it in your app code.
#. Write it back using the appropriate typed setter (for example ``setValueInt()``,
``setValueString()``, ``setValueBool()``, ...).
#. Afterwards, always use the matching typed getter.


Sensitive values
^^^^^^^^^^^^^^^^

Values Sensitivity
^^^^^^^^^^^^^^^^^^
When storing a new config value, you can mark it as sensitive.

When storing a new config value, it can be set as `sensitive`.
Configuration values set as `sensitive` are hidden from system reports and stored encrypted in the database.
Sensitive values are hidden from filtered listings/reports and are handled as protected
values in AppConfig storage.

.. code-block:: php

setValueString(
$appConfig->setValueString(
'myapp',
'mykey',
'myvalue',
sensitive: true
);

.. note::
Once set as `sensitive`, it can only be reverted using ``updateSensitive()``
Once set as sensitive, this can be changed later using ``updateSensitive()``.


Lazy Loading
Lazy loading
^^^^^^^^^^^^

To lighten the loading of all apps configuration at load, you have the possibility to set config values as `lazy`.
All `lazy` configuration values are loaded from the database once one is read.
To reduce memory and startup overhead, config values can be marked as lazy.

Non-lazy values are loaded first. Lazy values are loaded only when needed. When one lazy
value is requested, lazy values are loaded together.

.. code-block:: php

setValueString(
$appConfig->setValueString(
'myapp',
'mykey',
'myvalue',
lazy: true
);

.. note::
- Flag as `lazy` as much 'large block of text' entries (json, key pairs, ...) as possible,
- flag as `lazy` entries that are needed on quiet endpoints,
- do **not** flag as `lazy` part of code that might be called during the global loading of the instance and its apps.


Retrieving the configuration value will require to specify the fact that it is stored as `lazy`.
Retrieving a lazy value requires using the lazy read mode:

.. code-block:: php

getValueString(
$appConfig->getValueString(
'myapp',
'mykey',
'default',
lazy: true
);

Reading behavior with ``lazy`` parameter
""""""""""""""""""""""""""""""""""""""""

When reading values, the ``lazy`` argument controls which storage bucket is queried.

+----------------------+----------------------+----------------------------------------------+
| Stored key mode | Read with ``lazy`` | Result |
+======================+======================+==============================================+
| non-lazy | ``false`` | stored value |
+----------------------+----------------------+----------------------------------------------+
| non-lazy | ``true`` | stored value |
+----------------------+----------------------+----------------------------------------------+
| lazy | ``false`` | default value (lazy key is not searched) |
+----------------------+----------------------+----------------------------------------------+
| lazy | ``true`` | stored value |
+----------------------+----------------------+----------------------------------------------+

.. warning::
If a key may be lazy, read it with ``lazy: true`` to avoid silently getting defaults.

.. note::
- Requesting with ``1azy: false`` will returns the default value if configuration value is stored as `lazy`.
- Requesting with ``lazy: true`` will returns the correct value even if configuration value is stored as `non-lazy (as there is a huge probability that the `non-lazy` value are already loaded)
Some API methods explicitly ignore lazy filtering and may load all values.
Check each method description for warnings.

Choosing what should be lazy
""""""""""""""""""""""""""""

Good candidates for ``lazy: true``:

- Large values (for example JSON blobs, long text, large key/value maps).
- Values used only in specific flows (admin pages, background jobs, setup/migration tools).
- Values read infrequently or only after explicit user actions.

Usually keep as non-lazy (``lazy: false``):

- Small, frequently accessed values used on most requests.
- Values needed during app bootstrap, registration, capability wiring, or other early lifecycle code paths.
- Values used in hot paths (middleware, common service constructors, request-critical checks).

Practical rule:

- If a value is needed on most requests, keep it non-lazy.
- If it is large and only needed occasionally, make it lazy.

Consuming the AppConfig API
---------------------------

To consume the API, you first need to :ref:`inject<dependency-injection>` ``\OCP\IAppConfig``
You can inject either interface, depending on your use case:

- ``\OCP\IAppConfig`` (global API): use when you need to access configuration
for one or more app IDs explicitly.
- ``\OCP\AppFramework\Services\IAppConfig`` (AppFramework app-scoped API):
use inside your app when you want methods scoped automatically to your app ID.

See :ref:`dependency-injection` for injection details.

.. important::
Unless explicitly stated otherwise, examples in this page use the global
interface ``\OCP\IAppConfig`` (app ID passed explicitly).

If you inject ``\OCP\AppFramework\Services\IAppConfig``, methods are app-scoped
and you do not pass the app ID.


Storing a config value
^^^^^^^^^^^^^^^^^^^^^^

API provide multiple methods to store a config value, based on its type.
The global behavior for each of those methods is to call them using:
The API provides typed methods to store configuration values.

Common arguments are:

- app ID (``string``),
- config key (``string``),
- config value (typed),
- lazy flag (``bool``),
- sensitive flag (``bool``, where supported).

The return value is ``true`` if a database update was required.

- app id (string),
- config key (string),
- config value,
- lazy flag (boolean),
- sensitivity flag (boolean)
- ``setValueString(string $app, string $key, string $value, bool $lazy = false, bool $sensitive = false)``
- ``setValueInt(string $app, string $key, int $value, bool $lazy = false, bool $sensitive = false)``
- ``setValueFloat(string $app, string $key, float $value, bool $lazy = false, bool $sensitive = false)``
- ``setValueBool(string $app, string $key, bool $value, bool $lazy = false)``
- ``setValueArray(string $app, string $key, array $value, bool $lazy = false, bool $sensitive = false)``

The returned boolean will be true if an update of the database were needed.
AppFramework equivalents (app-scoped, no ``$app`` argument):

* ``setValueString(string $app, string $key, string $value, bool $lazy, bool $sensitive)``
* ``setValueInt(string $app, string $key, int $value, bool $lazy, bool $sensitive)``
* ``setValueFloat(string $app, string $key, float $value, bool $lazy, bool $sensitive)``
* ``setValueBool(string $app, string $key, bool $value, bool $lazy)``
* ``setValueArray(string $app, string $key, array $value, bool $lazy, bool $sensitive)``
.. code-block:: php

$appConfig->setAppValueString('mykey', 'myvalue', lazy: true);
$appConfig->setAppValueInt('retry_count', 3);
$appConfig->setAppValueArray('options', ['a' => true], sensitive: true);


Retrieving a config value
^^^^^^^^^^^^^^^^^^^^^^^^^

Configuration values are to be retrieved using one of the return typed method from the list:
Configuration values can be retrieved using typed getters:

* ``getValueString(string $app, string $key, string $default, bool $lazy)``
* ``getValueInt(string $app, string $key, int $default, bool $lazy)``
* ``getValueFloat(string $app, string $key, float $default, bool $lazy)``
* ``getValueBool(string $app, string $key, bool $default, bool $lazy)``
* ``getValueArray(string $app, string $key, array $default, bool $lazy)``
- ``getValueString(string $app, string $key, string $default = '', bool $lazy = false)``
- ``getValueInt(string $app, string $key, int $default = 0, bool $lazy = false)``
- ``getValueFloat(string $app, string $key, float $default = 0.0, bool $lazy = false)``
- ``getValueBool(string $app, string $key, bool $default = false, bool $lazy = false)``
- ``getValueArray(string $app, string $key, array $default = [], bool $lazy = false)``

AppFramework equivalents (app-scoped, no ``$app`` argument):

.. code-block:: php

$name = $appConfig->getAppValueString('display_name', 'default');
$count = $appConfig->getAppValueInt('retry_count', 0);
$enabled = $appConfig->getAppValueBool('enabled', false, lazy: true);


Managing config keys
^^^^^^^^^^^^^^^^^^^^

* ``getApps()`` returns list of ids of apps with stored configuration values
* ``getKeys(string $app)`` returns list of stored configuration keys for an app by its id
* ``hasKey(string $app, string $key, ?bool $lazy)`` returns TRUE if key can be found
* ``isSensitive(string $app, string $key, ?bool $lazy)`` returns TRUE if value is set as `sensitive`
* ``isLazy(string $app, string $key)`` returns TRUE if value is set as `lazy`
* ``updateSensitive(string $app, string $key, bool $sensitive)`` update `sensitive` status of a configuration value
* ``updateLazy(string $app, string $key, bool $lazy)`` update `lazy` status of a configuration value
* ``getValueType(string $app, string $key)`` returns bitflag defining the type of a configuration value
* ``deleteKey(string $app, string $key)`` delete a config key and its value
* ``deleteApp(string $app)`` delete all config keys from an app (using app id)
- ``getApps()`` returns app IDs that have stored configuration values.
- ``getKeys(string $app)`` returns stored keys for an app.
- ``searchKeys(string $app, string $prefix = '', bool $lazy = false)`` returns keys for an app matching a prefix.
- ``hasKey(string $app, string $key, ?bool $lazy = false)`` returns ``true`` if the key exists.
- ``isSensitive(string $app, string $key, ?bool $lazy = false)`` returns ``true`` if the value is sensitive.
- ``isLazy(string $app, string $key)`` returns ``true`` if the value is lazy.
- ``updateSensitive(string $app, string $key, bool $sensitive)`` updates sensitive status.
- ``updateLazy(string $app, string $key, bool $lazy)`` updates lazy status.
- ``getValueType(string $app, string $key)`` returns the type bitflag for a value.
- ``deleteKey(string $app, string $key)`` deletes one key and its value.
- ``deleteApp(string $app)`` deletes all keys for one app.

AppFramework equivalents include:

- ``getAppKeys()``
- ``hasAppKey(string $key, ?bool $lazy = false)``
- ``isSensitive(string $key, ?bool $lazy = false)``
- ``isLazy(string $key)``

.. note::
Some method allows ``$lazy`` to be ``null``, meaning that the search will be extended to all configuration values, `lazy` or not.
Methods with ``?bool $lazy`` can use ``null`` to search both lazy and non-lazy values.


Miscellaneous
^^^^^^^^^^^^^

API also provide extra tools for broaded uses
The API also provides additional helpers:

- ``getAllValues(string $app, string $prefix = '', bool $filtered = false)``
returns stored values for an app. If ``$filtered`` is ``true``, sensitive values are hidden.
- ``searchValues(string $key, bool $lazy = false)``
searches apps/values containing the specified key.
- ``getDetails(string $app, string $key)``
returns metadata/details about a key.
- ``convertTypeToInt(string $type)``
converts a human-readable type to a type bitflag.
- ``convertTypeToString(int $type)``
converts a type bitflag to a human-readable type.
- ``clearCache(bool $reload = false)``
clears internal cache.

* ``getAllValues(string $app, string $prefix, bool $filtered)`` returns all stored configuration values. ``$filtered`` can be set to TRUE to hide _sensitive_ values in the returned array
* ``searchValues(string $key, bool $lazy)`` search for apps and values that have a stored value for the specified configuration key.
* ``getDetails(string $app, string $key)`` get all details about a configuration key.
* ``convertTypeToInt(string $type)`` convert human readable string to the bitflag defining the type of a value
* ``convertTypeToString(int $type)`` convert bitflag defining the type of a value to human readable string
* ``clearCache(bool $reload)`` clear internal cache
AppFramework helper equivalent:

- ``getAllAppValues(string $key = '', bool $filtered = false)``


Constants and flags
^^^^^^^^^^^^^^^^^^^

``\OCP\IAppConfig`` exposes value-type constants and flags, including:

- ``FLAG_SENSITIVE`` (since 31),
- ``FLAG_INTERNAL`` (since 33; marks values as internal and eligible to be hidden from listings).