How to create config for your Shopware 6 plugin
What are the plugin configuration settings
In every application, including Shopware 6 plugins, you work with variables. They are the backbone of your program and you get them in various ways – from POST and GET requests to your controllers, from the URL, from the storefront, the admin forms etc. In those examples, the variables are passed to your code during runtime, based on the user’s action. That is absolutely OK, but there are some variables, that are practically constants in a sense, that your program needs them and their values might sometimes change, but not within one session.
Typical example would be a product import command, that connects to a remote data source. It needs the address and authentication data (username and password) to be able to connect, but you don’t want to fill them all the time, but also don’t want to put them into an URL for security reasons. You just want to have permanently stored variables, that the user of your plugin could edit and change, if necessary. And that is precisely what plugin configuration is for.
Where to find plugin configuration settings
Plugin configuration is available in the Shopware 6 Administration plugin list. Log in to the backend, the go to Settings – System – Plugins. Here you cas see the list of plugins, available in your store. When you click on the three dots, located in the last column of your plugin’s row, a menu will appear:
If the menu contains an item named “Config”, then this plugin is configurable. When you click on it, you will see configuration options for that particular plugin:
Please note, that if your Shopware 6 store contains multiple sales channels, you can set up config values separately for each of them. Just click on the uppermost select box and choose the sales channel, that you want to switch to. The screen then reloads and you will have the option to unlock and edit the values to be saved to that particular sales channel. If the ‘lock’ is left intact, then the sales channel will use the default values.
Also note, that some plugins can have their configuration (or a shortcut to it) in Admin – Settings – Plugins:
How to set up configuration settings
In order to set up the configuration page for your plugin, you need to add an XML file named config.xml to the src/Resources/config subdirectory of your Shopware 6 plugin. In this XML file, you will define the form elements, that you want to display to the user on the plugin configuration page. These elements represent the values, that you want to store to the plugin config.
Basic plugin config setup
Here is a rather long example of the config.xml file from a product import plugin, that I made some time a go:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
<?xml version="1.0" encoding="UTF-8"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/shopware/platform/master/src/Core/System/SystemConfig/Schema/config.xsd"> <card> <title>Import script configuration</title> <input-field type="bool"> <name>active</name> <label>Active</label> <helpText>You can turn on and off the scheduled script run here.</helpText> </input-field> <input-field type="multi-select"> <name>outputTypes</name> <label>Output Types</label> <helpText>Select one or more output types for the script. If none are selected, script will not output any messages.</helpText> <options> <option> <id>none</id> <name>Silent mode (no output)</name> </option> <option> <id>echo</id> <name>Direct HTML output</name> </option> <option> <id>log</id> <name>Log to file</name> </option> </options> </input-field> <input-field type="single-select"> <name>server</name> <label>Remote server</label> <helpText>Select a remote server as data source for the script to connect to.</helpText> <options> <option> <id>test</id> <name>Test server</name> </option> <option> <id>prod</id> <name>Production server</name> </option> </options> </input-field> <input-field type="int"> <name>maxFileCount</name> <label>Maximum number of files per one script run</label> <helpText>This is the maximum number of XML files, that the script will get from the remote GS1 server in one run. Leave blank to get all new files available. Please note, that high number of files can sometimes overload the server. Safe value should be around 5000.</helpText> </input-field> <input-field type="int"> <name>maxOperationCount</name> <label>Maximum number of database operations per batch</label> <helpText>This is the maximum number of items, that can be sent to database in one batch command. Batch operations save time, but depending on the local database setting, setting this number too high can cause errors and data not being saved. Safe value should be around 500.</helpText> </input-field> <input-field type="int"> <name>interval</name> <label>Time interval</label> <helpText>This is the time interval in seconds, in which the import script will be regularly executed.</helpText> </input-field> </card> <card> <title>Debug settings</title> <input-field type="textarea"> <name>forceFiles</name> <label>Files to be used by the import</label> <copyable>true</copyable> <helpText>If you want the script to work with (and just with) some particular files, put their names here with one space between them and activate below. Please make sure these files exist in the location, from which the script will try to get them.</helpText> </input-field> <input-field type="bool"> <name>useForceFiles</name> <label>Force the import to use the selected file(s)</label> <helpText>Activate this to force the script to use the files from the input above. This is an override, therefore all other files will be ignored.</helpText> </input-field> <input-field type="bool"> <name>useLocalFiles</name> <label>Force the import to use the locally stored files</label> <helpText>Activate this to force the script to use the files from the local storage. Please note, that you can also use the forcing of the above selected files in combination with using local storage.</helpText> </input-field> <input-field type="bool"> <name>ignoreOldFiles</name> <label>Ignore old files check</label> <helpText>This will skip the check of the files, that we already worked with and will not exclude them from the script run. Please be aware, that this is just a debugging feature and can result in updating the products with older data.</helpText> </input-field> <input-field type="bool"> <name>keepOldFilesInfo</name> <label>Keep old files information</label> <helpText>This will cause, that the list of files, that were already processed and are not found on the remote server, will not be cleared.</helpText> </input-field> <input-field type="bool"> <name>ignoreLastUpdate</name> <label>Ignore last updated timestamp check</label> <helpText>This will skip the timestamp check before parsing product parameters.</helpText> </input-field> </card> <card> <title>Production server configuration</title> <input-field> <name>address</name> <label>Server address</label> <copyable>true</copyable> <helpText>Address of the remote server</helpText> </input-field> <input-field type="int"> <name>portNumber</name> <label>Port Number</label> <copyable>true</copyable> <helpText>Port number for connecting to the remote server</helpText> <defaultValue>555</defaultValue> </input-field> <input-field> <name>userName</name> <label>Username</label> <copyable>true</copyable> <helpText>The username for logging in</helpText> </input-field> <input-field> <name>password</name> <label>Password</label> <copyable>true</copyable> <helpText>The password for logging in</helpText> </input-field> <input-field> <name>directory</name> <label>Directory</label> <helpText>The directory on the remote server, that contains the XML files for the import.</helpText> </input-field> </card> <card> <title>Test server configuration</title> <input-field> <name>addressTest</name> <label>Server address</label> <copyable>true</copyable> <helpText>Address of the remote server</helpText> </input-field> <input-field type="int"> <name>portNumberTest</name> <label>Port Number</label> <copyable>true</copyable> <helpText>Port number for connecting to the server</helpText> <defaultValue>666</defaultValue> </input-field> <input-field> <name>userNameTest</name> <label>Username</label> <copyable>true</copyable> <helpText>The username for logging in</helpText> </input-field> <input-field> <name>passwordTest</name> <label>Password</label> <copyable>true</copyable> <helpText>The password for logging in</helpText> </input-field> <input-field> <name>directoryTest</name> <label>Directory</label> <helpText>The directory on the remote server, that contains the XML files for the import.</helpText> </input-field> </card> </config> |
As you see, the plugin config is organized into cards for better readability. In contrast to Magento 2 module config, in Shopware 6, this division is purely cosmetic and has no influence, on how you read your config variables. You give the name to your card in its sub-element called title. In backend, the title “Import script configuration” looks like this:
The rest is basically just form inputs for the various variables. Each of these inputs has a type, which decides, if a select, multi-select, text area etc. will be displayed. If you omit the type, the system assumes, that you just want to have a basic text input there. You can also specify “int” or “float”, which means, that the system will automatically create input, that will permit the user to put in just appropriate numerical values. Here you can see the complete list of basic types of inputs, used for plugin config in Shopware 6:
Type | Displayed item | Additional settings |
bool | On/off switch | |
checkbox | Checkbox | |
colorpicker | Color selector | |
date | Date selector | |
datetime | Date and time selector | |
float | One-line input for decimals | |
int | One-line input for integers | |
multi-select | Multi-select input | options, placeholder |
password | One-line input for password | placeholder |
single-select | Single-select input | options, placeholder |
text | One-line text input | copyable, placeholder |
textarea | Multi-line text input | copyable, placeholder |
time | Time selector | |
url | One-line input for URL | copyable, placeholder |
As the table shows, the additional settings are possible to use for certain input types only. For selects, you can use, and in fact need to use, the options. Copyable means, that there will be a button, allowing a quick copy of the input contents. And placeholder is a text, that is displayed, when there is no value in the input.
Regardless of the input type, it must always have at least a name. This name is also the name of the variable, that you will read from the config during your plugin’s runtime. The name has to be unique per plugin! The label should also be present. As you can see on the screenshot above, its visual representation depends on the input type a bit, so in a switch, the label “Active” is inline, while in most other cases like “Output type”, it is above the input itself. Useful, but not mandatory is the helpText element, which looks like this:
There are also ‘disabled’ and ‘defaultValue’, which I think are quite self-explanatory. However, for some more complex cases, there are some caveats. Therefore, I have written a separate article on the topic of setting the defaults in plugin config. You might want to check it, especially if you want to use the Shopware 6 components in your plugin’s configuration page.
Using Shopware 6 components in plugin config
You can also use Shopware 6 components in plugin configuration. For the whole selection of them, please see the Shopware 6 official component library, but as an example, I would like to introduce one, that I found to be the most useful: the Entity multi-ID select. This component is a multi-select, that you probably already know from the backend. It allows you to specify any entity, available in your Shopware 6 installation, including your own entities. The items from this entity are then available for selecting and their IDs are saved to the administration as an array. The structure of the components is a bit different from the standard inputs, but as you see in the following example, not that much:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0" encoding="UTF-8"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/shopware/platform/master/src/Core/System/SystemConfig/Schema/config.xsd"> <card> <title>Configuration</title> <component name="sw-entity-multi-id-select"> <name>selectedCountries</name> <entity>country</entity> <label>Choose one or more countries</label> </component> </card> </config> |
This config.xml translates to this Administration screen:
How to get plugin config variables
Inside Shopware 6, the plugin configuration variables are stored in the table, named system_config. In the column, named configuration_key, is the name of the variable, in format PluginName.config.VariableName. In the column, named configuration_value, is the actual value of the variable. This column is in JSON format and therefore it is very flexible and able to store multiple formats of data, including arrays. You could of course go here directly, if you want to read a variable from your plugin’s config. However, the standard and much more convenient way is to use the SystemConfigService class. So how do you use it? Quite simply, really. Just inject it to your class and then obtain the desired values by calling the get method like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?php namespace SomeImport\Components; use Shopware\Core\System\SystemConfig\SystemConfigService; class SomeClass { const MAX_OPERATION_COUNT = 'SomeImport.config.maxOperationCount'; private $configService; public function __construct( SystemConfigService $configService, ) { $this->configService = $configService; } public function someFunction () { //read the value of variable maxOperationCount $maxOperationCount = $this->configService->get(self::MAX_OPERATION_COUNT); } } |
Please note, that I have stored the whole path of the config variable to a constant. I consider this a good practice, as it reduces the chance of typos and helps consistency between classes, not mentioning the fact, that you just have to edit it on one place in the code, if the config value changes or gets replaced by another. In larger projects, I tend to have a special class just for config constants to keep things tidy and in one place.
If you want to get all available values for one particular plugin or you need to get the values from another plugin to use them in this one, you can use the getDomain method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<?php namespace SomeImport\Components; use Shopware\Core\System\SystemConfig\SystemConfigService; class SomeClass { const DOMAIN = 'SomeImport'; private $configService; public function __construct( SystemConfigService $configService, ) { $this->configService = $configService; } public function someFunction () { //get the variables from this plugin's config as an array $domain = $this->configService->getDomain(self::DOMAIN); //go through the config variables foreach ($domain as $key => $value) { //get the name of the config variable var_dump($key); //get the value of the config variable var_dump($value); } } } |
How to change plugin config values in runtime
Sometimes you might want to actually reverse the process and change the config value from runtime. It is as simple as getting it. Just use the set method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?php namespace SomeImport\Components; use Shopware\Core\System\SystemConfig\SystemConfigService; class SomeClass { const MAX_OPERATION_COUNT = 'SomeImport.config.maxOperationCount'; private $configService; public function __construct( SystemConfigService $configService, ) { $this->configService = $configService; } public function someFunction () { //set the value of variable maxOperationCount to 100 $maxOperationCount = $this->configService->set(self::MAX_OPERATION_COUNT, 100); } } |
There is also one option, that is not used often, but it is good to know it. If you have a Shopware 6 store with multiple sales channels, you are able to get and set the settings separately for each of them. Just use the sales channel ID as an additional parameter to get or set method and you will read or write the config value for that particular sales channel.
Hi I am Preeti, new in shopware development.
i want to display some country displayed as default using this
selectedCountries
country
Choose one or more countries
Please guide me how to do this,
Hello, that is an interesting topic. I have actually delved into it a bit and in the end written a new article, named How to set up default values for Shopware 6 plugin config ( https://shopwarian.com/how-to-set-up-default-values-for-shopware-6-plugin-config/ ). You should find the answer to your question, along with examples there.
Thank you, Jan, when pure shopware documentation missing mandatory information your guide gives it in the right form for developers.
Thanks. When I am able to figure something out, I am glad to share the knowledge. 🙂