Use Magento configuration
In Magento, many features have related configurations. Each one of them will influence how your shop runs. You might want to access them from your Front-Commerce application to give merchants more autonomy. This guide explains how to achieve this.
Configurations usually are available under the
Stores > Settings > Configurations page. Configurations are stored in a
unified way in the Magento database and as a developer, you will have a unified
way to fetch them. In Front-Commerce you have two possibilities:
- Reuse Magento's GraphQL schema
- Fetch configurations with a REST endpoint
In this guide, we will focus on the REST endpoint.
Fetch configurations from /frontcommerce/storeConfigs Magento endpoint
The REST endpoint is a custom one added by Front-Commerce's Magento module.
http://magento.test/rest/V1/default/frontcommerce/storeConfigs?keys[]=design/header/welcome
This endpoint is protected and only users having the permission
Magento_Config::config have the right get data from this endpoint. In
Front-Commerce everything is already setup so that you don't need to care about
this permission. But if you want to test this endpoint manually (with cURL,
Postman or the tool of your choice), please make sure that you have added an
oAuth2 authentication with the correct secrets.
Moreover, this endpoint only exposes keys that were previously defined in the DI
of your Magento. By default only design/footer/absolute_footer and
design/header/welcome will be available on the endpoint. This allows to avoid
exposing sensitive information and reduces the attack surface of your API.
However, you can add in your own di.xml the following XML to ensure that more
keys are available in your endpoint.
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- ... -->
+ <type name="\FrontCommerce\Integration\Model\Config\ConfigKeyChecker">
+ <arguments>
+ <argument name="acceptList" xsi:type="array">
+ <item name="your/config/path" xsi:type="string">your/config/path</item>
+ <item name="your/config/path2" xsi:type="string">your/config/path2</item>
+ </argument>
+ </arguments>
+ </type>
</config>
In this case we've decided to expose the keys your/config/path and
your/config/path2. However you can expose any configuration from your Magento.
Once you've set the new arguments to the ConfigKeyChecker class, you need to
update your DI in magento by running the following command:
php bin/magento setup:di:compile.
The endpoint should now expose your config to any authenticated requests with
the Magento_Config::config permission.
// Request (with additional Authorization headers)
http://magento.test/rest/V1/default/frontcommerce/storeConfigs?keys[]=your/config/path
// Response
[
{
"key": "your/config/path",
"value": "My config value"
},
]
Fetch configurations in your Front-Commerce application
Once you've exposed the configurations on your Magento endpoint, you will need to use these configurations in Front-Commerce. There are two ways to do so:
- If you need these configurations client side, you can expose a configuration in your GraphQL
- If you need these configurations server side, you can use the MagentoConfig loader
Expose a configuration in your GraphQL
When exposing a new field in GraphQL, you will write a GraphQL module in order
to
extend the GraphQL schema
and then write something along those lines in your schema.gql:
import { createGraphQLModule } from "@front-commerce/core/graphql";
export default createGraphQLModule({
namespace: "AcmeExtension",
typeDefs: /* GraphQL */ `
extend type Query {
fieldName: String
}
`,
});
In the case of a configuration coming from Magento, it is the same thing but you
need to add a @magentoConfig directive after your field to tell your GraphQL
which configuration key is associated with this field.
import { createGraphQLModule } from "@front-commerce/core/graphql";
export default createGraphQLModule({
namespace: "AcmeExtension",
dependencies: ["Magento2/Store"],
typeDefs: /* GraphQL */ `
extend type Query {
fieldName: String @magentoConfig(key: "your/config/path")
}
`,
});
Please make sure to add Magento2/Store to your GraphQL module's dependencies
to make sure that the @magentoConfig directive is available.
export default {
// ...
dependencies: ["Magento2/Store"],
// ...
};
Under the hood, this directive will automatically create a resolver for this field that will fetch the configuration from Magento. You can use this field however you want in your React application.
Please note that in this example, we are adding the field to the Query type,
but it can be any type in your GraphQL schema.
My field type is not a String
In the previous example, we have used a String to represent the configuration.
however in some cases you don't want to expose a String, but an Int, or even
more complex types like Wysiwyg or Product. To do so, you will need to:
- update your schema with the correct type
- add a resolver that transforms the configuration value in what you need to represent this type
Let's say that our configuration is a Wysiwyg. This means that you will need
to operate the following changes:
extend type Query {
- fieldName: String @magentoConfig(key: "your/config/path")
+ fieldName: Wysiwyg @magentoConfig(key: "your/config/path")
}
export default createGraphQLRuntime({
resolvers: {
Query: {
fieldName: ({ magentoConfig }, _, { loaders }) => {
// the configuration value from the @magentoConfig is available in
// the magentoConfig key of the first argument of your resolver
return loaders.Wysiwyg.parse(magentoConfig, "MagentoWysiwyg");
},
},
},
});
Use the MagentoConfig loader
If you can't use the @magentoConfig directive, you can also fetch the
configuration from a loader available in Front-Commerce:
loaders.MagentoConfig.
Please make sure to add Magento2/Store to your GraphQL module's dependencies
to make sure that the @magentoConfig directive is available.
export default {
// ...
dependencies: ["Magento2/Store"],
// ...
};
This means that in your resolvers, you can write the following code:
export default createGraphQLRuntime({
resolvers: {
Query: {
fieldName: ({ magentoConfig }, _, { loaders }) => {
return loaders.MagentoConfig.load("your/config/path");
},
},
},
});
Use Magento's storeConfig GraphQL query
Front-Commerce also provides a way to access configurations from Magento's
storeConfig GraphQL query. With just a few easy steps, you can access
configurations without relying on Front-Commerce's Magento2 PHP extension. This
section explains the different steps involved.
Magento: expose Your Configuration on the StoreConfig type
The first step is to ensure that your configuration is exposed on the
StoreConfig type in Magento. You can refer to
the storeConfig query documentation
for more details on which configurations are available by default.
If you need to extend the existing schema, follow this helpful guide on how to extend configuration data. This step sets the foundation for accessing your configurations using the GraphQL query.
You must now be able to query Magento's GraphQL endpoint to fetch your configuration with a query of the following form:
{
storeConfig {
is_negotiable_quote_active
my_custom_config_value
}
}
In the current state, only 1 level of configuration can be queried by Front-Commerce. Nested configurations aren't supported.
Use MagentoGraphQLConfig loader for fetching configurations
Once your configuration is exposed on Magento, you can use the
MagentoGraphQLConfig loader to fetch it. This loader (from the
Magento2/Store GraphQL module) acts as a bridge between your GraphQL resolvers
and the underlying configurations in Magento.
Here's an example of how you can use the MagentoGraphQLConfig loader:
export default createGraphQLRuntime({
resolvers: {
MyApp: {
configurations: async (_parentData, _args, { loaders }) => {
const configurations =
await loaders.MagentoGraphQLConfig.loadStoreConfigurations([
{
// Magento configuration key, for caching
magentoConfigKey:
"btob/website_configuration/negotiablequote_active",
// Magento StoreConfig GraphQL field name, for fetching
graphQLFieldName: "is_negotiable_quote_active",
},
{
magentoConfigKey: "my/custom/app/config_value",
graphQLFieldName: "config_value",
},
]);
// the loader returns an array of values, so you can use them by destructuring them
const [isNegotiableQuoteActive, configValue] = configurations;
return { isNegotiableQuoteActive, configValue };
},
},
},
});
This example demonstrates how you can fetch multiple configurations at once,
specifying the magentoConfigKey and the corresponding graphQLFieldName for
each configuration. This provides an efficient way to retrieve your
configurations while benefiting from Front-Commerce configuration caching
mechanisms. The cache is shared with the
MagentoConfig loader.
These values should be reverse-engineered from Magento's GraphQL definitions.
Indeed, the magentoConfigKey is the value from the <item></item> element
defining the storeConfig GraphQL field exposed in Magento.
Here is an example of how the above my/custom/app/config_value
would be exposed in Magento to extend configuration data:
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\StoreGraphQl\Model\Resolver\Store\StoreConfigDataProvider">
<arguments>
<argument name="extendedConfigData" xsi:type="array">
<item name="config_value" xsi:type="string">my/custom/app/config_value</item>
</argument>
</arguments>
</type>
</config>
The my/custom/app/config_value is the value to use for magentoConfigKey in
this example.