5

I'm doing some server configuration related tasks and was looking for a way to configure the theme of a store/website via the command-line.

I'm setting up a store with a custom theme (e.g. "Vendor/code") and I would like to activate it without entering the adminhtml website but set the theme on the command-line / in the shell / bash script.

2
  • Created custom theme, you want to set for store ? Oct 24, 2016 at 10:19
  • @SHPatel: Yes, created a custom theme and then doing semi/automated deployments. Edited the question to reflect this better and have a bit more context.
    – hakre
    Oct 24, 2016 at 11:07

4 Answers 4

5

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.

4

I was not able to find a direct Magento CLI command so far, I could work around with a Bash and Magerun:

$ THEME_ID="$(n98-magerun2.phar dev:theme:list --format=csv \
  | grep 'Vendor/code' | cut -d, -f1)" \
  ; test -n "${THEME_ID}" \
  && n98-magerun2.phar config:set design/theme/theme_id "${THEME_ID}"

This sequence sets the configuration path for the theme_id to the one of the named theme (by it's code, which is "Vendor/code" in the example).

In case the operation fails, this has a non-zero status.

1

Because this is still rather hard to do, I created a simple module to allow for enabling a theme from the CLI anyway: https://github.com/yireo/Yireo_ThemeCommands Example command would be bin/magento theme:change Hyva/default 1 stores.

-1

The only command related to themes out of the box in Magento 2 is php bin/magento theme:uninstall which can be used to uninstall a theme.

I suggest you create your own command following the example in the sample module so you can develop your custom code to configure themes properly.

Also I suggest you read the official documentation to create your own command: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/cli-cmds/cli-howto.html

1
  • 1
    I would consider creating a CLI command off-topic in the light of an answer (yes it's possible, and programming it yourself is always the solution of everything, and so its kinda superfluous for an answer here) - and consider that more a comment. But thanks for your efforts and your commentary.
    – hakre
    Oct 24, 2016 at 10:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.