Configuration as Code

app:config:dump writes settings into config.php and app:config:import applies them, so no deploy depends on an admin click.

Syntaxbin/magento app:config:dump [scopes system themes i18n]

A setting that exists only because somebody clicked Save in the admin is not reproducible. Rebuild the environment, or restore a colleague's database, and the setting is different. Magento's answer is to move configuration into a file that is committed and applied by the deploy.

Dump

bin/magento app:config:dump reads the current configuration and writes it into app/etc/config.php, sending anything declared sensitive or environment-specific to app/etc/env.php instead. It takes an optional space-separated list of config types: scopes, system, themes, i18n. Omitting the list is shorthand for dumping all of them.

Import

bin/magento app:config:import reads config.php and writes the parts that can only live in the database, such as websites and store views. bin/magento setup:upgrade invokes app:config:import itself, so a deploy that already runs setup:upgrade needs no extra step.

What trips people up

Every value in config.php becomes read-only in the admin. That is the point, and it is also the support ticket: a merchant reports a greyed-out field. Handing it back means deleting that path from config.php and deploying again. Dumping everything on a developer machine also commits your local base URLs, so dump the config type you mean rather than all four.

Example

Example · php
<?php
// app/etc/config.php - generated by bin/magento app:config:dump, commit this file
return [
    'modules' => [
        'Acme_Loyalty' => 1,
    ],
    'system' => [
        'default' => [
            'loyalty' => [
                'general' => [
                    'enabled' => '1',
                    'points_per_currency' => '10',
                ],
            ],
        ],
        'websites' => [
            'base' => [
                'loyalty' => [
                    'general' => [
                        'points_per_currency' => '20',
                    ],
                ],
            ],
        ],
    ],
];

When to use it

  • Make a new environment come up with the same settings as production, with no admin work.
  • Review a configuration change in a pull request instead of discovering it in production.
  • Lock settings that support staff should not be able to change through the admin.
  • Stop a release failing because somebody forgot to tick a box after deploying.

More examples

Dumping only what you mean to commit

The bare command is convenient and indiscriminate: it also picks up scopes, which carries the website, store group and store view rows from your local database, and themes. Naming system keeps the diff to the configuration tree, but that tree is where base URLs live too, so web/unsecure/base_url and friends land in the file along with everything else saved in core_config_data. Always read the diff before committing, because every path that lands in the file is a field a merchant can no longer edit, and a local base URL locked into config.php follows the deploy into the next environment.

Example · bash
# Shorthand: all four config types at once.
$ bin/magento app:config:dump

# Narrow: only the system configuration tree.
$ bin/magento app:config:dump system

$ git diff --stat app/etc/config.php
 app/etc/config.php | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

$ git add app/etc/config.php && git commit -m "Lock loyalty settings"

Where import fits in a deploy

setup:upgrade finds and runs the app:config:import command itself, so listing both is harmless but unnecessary. If your pipeline deliberately skips setup:upgrade, run bin/magento app:config:import on its own, otherwise a newly committed store view in config.php never reaches the database. --keep-generated is for pipelines where setup:di:compile already ran at build time.

Example · bash
$ bin/magento maintenance:enable
$ bin/magento setup:upgrade --keep-generated
  # setup:upgrade runs app:config:import internally; config.php is applied here
$ bin/magento cache:flush
$ bin/magento maintenance:disable

Keeping a credential out of the committed file

Declare this before the first app:config:dump, not after. TypePool is what tells the dump to put loyalty/api/key into env.php instead of config.php; without it the key goes into the file you are about to commit, and removing it from a later commit does not remove it from the repository history. Run bin/magento setup:di:compile and bin/magento cache:flush, then dump.

Example · xml
<!-- app/code/Acme/Loyalty/etc/di.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Config\Model\Config\TypePool">
        <arguments>
            <argument name="sensitive" xsi:type="array">
                <item name="loyalty/api/key" xsi:type="string">1</item>
            </argument>
        </arguments>
    </type>
</config>

Discussion

  • Be the first to comment on this lesson.