This does not accomplish OP's goal of utilizing the Magento CLI, however it does work for usage in automation which is what OP (and myself) was looking to achieve.
Edit: 2022.08.02
A "Magento way" to programmatically revise the theme is to utilize dependency injection to revise the value of the frontend
key of the $themes
array passed to the constructor of the \Magento\Theme\Model\View\Design
object. This array serves to configure what the default theme will be for an area, if one is not already configured (refer to the logic in getConfigurationDesignTheme()
of this same class).
This approach therefore works well in deployment pipelines, if we desire to have the theme set upon initial setup:install
and we do not yet know the theme.theme_id
database value that will belong to our theme.
Example etc/di.xml
:
<?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\Theme\Model\View\Design">
<arguments>
<argument name="themes" xsi:type="array">
<item name="frontend" xsi:type="string">Foo/bar</item>
</argument>
</arguments>
</type>
</config>
Because we are seeking to override existing XML configuration of Magento_Theme
, be sure that the module also specifies a <sequence>
node in its etc/module.xml
file to assure the custom module is loaded afterwards and its value takes precedence.
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Foo_Bar">
<sequence>
<module name="Magento_Theme"/>
</sequence>
</module>
</config>
If you have a multi-store installation with various themes per store, this approach would not be suitable as it serves to only set the fallback theme when none is set.
In a multi-store situation, a "Magento way" to accomplish theme configuration via the code would be to register a Setup/RecurringData.php
script. This script would have to perform something along the lines of instantiating a Theme Collection object, filtering by the code
your theme would result in, retrieving the theme_id
, then saving the design/theme/theme_id
value for the appropriate scope.
Despite probably only needing to do this once, it is unfortunate that we cannot merely create a Data Patch to reliably configure this upon first setup:install
of a project. The reason being, is that it is Magento\Theme\Setup\RecurringData
that registers into the theme
table the existence of themes. Because RecurringData scripts run after Data Patches, a record for our theme would not yet exist in the theme
table at the time that our Data Patch runs. Therefore we must resort to a RecurringData script instead.
Original Answer:
If your automation has access to the database, we can set the theme by querying the appropriate tables and performing INSERT statements.
Set Theme at a global scope:
INSERT INTO core_config_data
VALUES
(NULL, 'default', 0, 'design/theme/theme_id', (SELECT theme_id FROM theme WHERE code = 'VendorName/ThemeNameOne'))
Set Theme at a Website scope:
INSERT INTO core_config_data
VALUES
(NULL, 'websites', (SELECT website_id FROM store_website WHERE code = 'website_code_one'), 'design/theme/theme_id', (SELECT theme_id FROM theme WHERE code = 'VendorName/ThemeNameOne')),
(NULL, 'websites', (SELECT website_id FROM store_website WHERE code = 'website_code_two'), 'design/theme/theme_id', (SELECT theme_id FROM theme WHERE code = 'VendorName/ThemeNameTwo'))
;
Set Theme at a Store scope:
INSERT INTO core_config_data
VALUES
(NULL, 'stores', (SELECT store_id FROM store WHERE code = 'store_code_one'), 'design/theme/theme_id', (SELECT theme_id FROM theme WHERE code = 'VendorName/ThemeNameOne')),
(NULL, 'stores', (SELECT store_id FROM store WHERE code = 'store_code_two'), 'design/theme/theme_id', (SELECT theme_id FROM theme WHERE code = 'VendorName/ThemeNameTwo'))
;
Variable strings above to replace:
website_code_one
website_code_two
store_code_one
store_code_two
VendorName/ThemeNameOne
VendorName/ThemeNameTwo
If you have more or less themes to set in your automation process, we can see above how we'll simply need to add/remove VALUE sets to the INSERT query.
Final Note:
The queries above are under the assumption that there are no records in core_config_data
for your themes. This will be the case if your automated process is performing a fresh installation of Magento, or performing a fresh install + Magento 1 to Magento 2 migration. If this is not the case for you and you have records with matching scope,scope_id,path
values, you'll need to revise your strategy to either perform a DELETE
query prior to, revise the queries to be an UPDATE
query.