Bonne façon de mettre à jour le parent d'un thème dans Magento 2

14

Dans Magento 2, vous pouvez spécifier un thème parent dans le theme.xmlfichier d' un thème .

<theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd">
    <title>Theme Title</title>
    <parent>Package/base-theme</parent>
    <media>
        <preview_image>media/preview.jpg</preview_image>
    </media>
</theme>

La première fois que Magento voit un thème, il utilise cette valeur pour définir un parent_iddans le themetableau. C'est la source de vérité pour savoir où se trouve le parent d'un thème.

Cependant, si vous essayez de modifier cette valeur après l'ajout d'un thème au système , Magento ne met pas à jour la parent_idcolonne et les Magento\Theme\Model\Themeobjets instanciés auront toujours le thème parent d'origine. (Même si vous videz le cache.)

Je peux résoudre ce problème en modifiant manuellement la parent_idvaleur - cela semble être un hack. Où est parent_idnormalement défini dans le code de base de Magento, et quelles actions utilisateur déclenchent cela? c'est-à-dire qu'il existe un moyen de dire à Magento "veuillez recharger ce thème"

Alan Storm
la source
2
Oui, je l'ai également remarqué et la seule façon que j'ai trouvée de le modifier après l'enregistrement du thème est de modifier directement la base de données. Peut-être un bug?
Gareth Daine

Réponses:

2

MISE À JOUR AU 20160310

Conclusion

Il est toujours défini via updateTheme()ou depuis la collection (via DB) si votreappState->getMode() == AppState::MODE_PRODUCTION

Répondre

Pour répondre à la question Comment faire pour que Magento recharge le fichier theme.xml la réponse est:

Définissez l'état de l'application sur developerusing SetEnv MAGE_MODE developerin .htaccess(ou équivalent nginx), puis connectez-vous à la zone d'administration (ou actualisez n'importe quelle route d'administration) pour le déclencher Magento\Theme\Model\Theme\Plugin\Registration::beforeDispatch().

La table thématique de la base de données est mise à jour en raison de

\\Magento\Theme\Model\Theme\Plugin\Registration::updateThemeData()
\\...
$themeData->setParentId($parentTheme->getId());`.
\\...

Voir l'analyse ci-dessous pour plus de détails.

Une analyse

Wow, le code Magento 2 me semble vraiment complexe. Avez-vous étudié cette fonction beforeDispatch()qui appelle updateThemeData()mais seulementif ($this->appState->getMode() != AppState::MODE_PRODUCTION)

//namespace: namespace Magento\Theme\Model\Theme\Plugin;
//class: Registration
//file: app/code/Magento/Theme/Model/Theme/Plugin/Registration.php 

     /**
     * Add new theme from filesystem and update existing
     *
     * @param AbstractAction $subject
     * @param RequestInterface $request
     *
     * @return void
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function beforeDispatch(
        AbstractAction $subject,
        RequestInterface $request
    ) {
        try {
            if ($this->appState->getMode() != AppState::MODE_PRODUCTION) {
                $this->themeRegistration->register();
                $this->updateThemeData();
            }
        } catch (LocalizedException $e) {
            $this->logger->critical($e);
        }
    }

Vous avez probablement parcouru ce code.

beforeDispatch()est appelé uniquement via les routes d'administration et non sur les routes frontales. Voici une trace:

#0 [internal function]: Magento\Theme\Model\Theme\Plugin\Registration->beforeDispatch(Object(Magento\Backend\Controller\Adminhtml\Dashboard\Index\Interceptor), Object(Magento\Framework\App\Request\Http))
#1 \magento2\lib\internal\Magento\Framework\Interception\Interceptor.php(122): call_user_func_array(Array, Array)
#2 \magento2\var\generation\Magento\Backend\Controller\Adminhtml\Dashboard\Index\Interceptor.php(39): Magento\Backend\Controller\Adminhtml\Dashboard\Index\Interceptor->___callPlugins('dispatch', Array, Array)
#3 \magento2\lib\internal\Magento\Framework\App\FrontController.php(55): Magento\Backend\Controller\Adminhtml\Dashboard\Index\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#4 [internal function]: Magento\Framework\App\FrontController->dispatch(Object(Magento\Framework\App\Request\Http))
#5 \magento2\lib\internal\Magento\Framework\Interception\Interceptor.php(74): call_user_func_array(Array, Array)
#6 \magento2\lib\internal\Magento\Framework\Interception\Chain\Chain.php(70): Magento\Framework\App\FrontController\Interceptor->___callParent('dispatch', Array)
#7 \magento2\lib\internal\Magento\Framework\Interception\Interceptor.php(136): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Framewo...', 'dispatch', Object(Magento\Framework\App\FrontController\Interceptor), Array, 'install')
#8 \magento2\lib\internal\Magento\Framework\Module\Plugin\DbStatusValidator.php(69): Magento\Framework\App\FrontController\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Request\Http))
#9 [internal function]: Magento\Framework\Module\Plugin\DbStatusValidator->aroundDispatch(Object(Magento\Framework\App\FrontController\Interceptor), Object(Closure), Object(Magento\Framework\App\Request\Http))
#10 \magento2\lib\internal\Magento\Framework\Interception\Interceptor.php(141): call_user_func_array(Array, Array)
#11 \magento2\var\generation\Magento\Framework\App\FrontController\Interceptor.php(26): Magento\Framework\App\FrontController\Interceptor->___callPlugins('dispatch', Array, Array)
#12 \magento2\lib\internal\Magento\Framework\App\Http.php(115): Magento\Framework\App\FrontController\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#13 \magento2\lib\internal\Magento\Framework\App\Bootstrap.php(258): Magento\Framework\App\Http->launch()
#14 \magento2\index.php(39): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http))

En fait, je vois des beforeDispatch()appels updateThemeData()qui contiennent ce nugget:

//namespace: namespace Magento\Theme\Model\Theme\Plugin;
//class: Registration
//file: app/code/Magento/Theme/Model/Theme/Plugin/Registration.php 
//function: updateThemeData()

//...
            if ($themeData->getParentTheme()) {
                $parentTheme = $this->themeLoader->getThemeByFullPath(
                    $themeData->getParentTheme()->getFullPath()
                );
                $themeData->setParentId($parentTheme->getId());
            }
//...

Ce qui semble faire (enfin) référence à un chemin XML de configuration, $themeData->getParentTheme()->getFullPath()mais cette fonction utilise toujours $themeData->getParentTheme(). Oh je pense que la logique est ' Si je mets à jour un thème enregistré qui a un parentId dans la collection (via la base de données), recherchez un chemin parent dans la configuration et mettez à jour la collection ''.Alors peut-être que c'est ça.

Sinon, je ne sais absolument pas comment Magento\Theme\Model\Theme::getParentTheme()implémenter getParentId()ce qui est déclaré dans l'interface du thème. Ce n'est certainement pas magique. Comme vous le dites, il doit provenir de la base de données via la collection ou du chemin XML de configuration du thème (s'il a changé ou n'est pas encore défini), mais je ne trouve pas de définition de getParentId(). Peut-être qu'il est toujours défini via updateTheme()OR à partir de la collection (via DB), tant pis si votre appState->getMode() == AppState::MODE_PRODUCTION.

J'ai trouvé utile de glaner des informations de l'intérieur updateThemeData()en ajoutant une sortie de journal:

//namespace: namespace Magento\Theme\Model\Theme\Plugin;
//class: Registration
//file: app/code/Magento/Theme/Model/Theme/Plugin/Registration.php 
//function: updateThemeData()

//...
            if ($themeData->getParentTheme()) {
                $parentTheme = $this->themeLoader->getThemeByFullPath(
                    $themeData->getParentTheme()->getFullPath()
                );
            $this->logger->addDebug("Theme parent full path ".$themeData->getParentTheme()->getFullPath());
            $this->logger->addDebug("Theme parent new ID ".$parentTheme->getId());                    $themeData->setParentId($parentTheme->getId());
            }
//...

Qui se connectera /var/log/debug.log. Lorsque l'état de l'application est défini sur developerJe peux voir que l'ID parent est toujours défini à chaque actualisation de la page d'administration, qu'il ait été modifié theme.xmlou non. Avec l'état de productionl' application, la fonction n'est jamais exécutée, je conclus donc:

Il est toujours défini via updateTheme()OR à partir de la collection (via DB), tant pis si votreappState->getMode() == AppState::MODE_PRODUCTION

Je pense que vous êtes probablement tous en developerétat d'application. defaultl'état de l'application se déclenchera updateThemeData()aussi bien sûr. Lors du débogage, j'ai enregistré le chemin complet du thème pour le thème parent de Luma qui était frontend/Magento/blank. La capitale Mm'a surpris alors peut-être quelque chose à surveiller.

Malachy
la source
0

Ce qui précède ne semble pas fonctionner pour moi, alors je suis allé avec le hack.

J'espère que cela aide quelqu'un.

using the command line

 mysql

 SHOW databases;

 use magento; (or whatever your DB's name is)

 SHOW tables

 SELECT * FROM theme; 

(Check the **parent_id** of theme in question, it should be the same number as **theme_id** of theme you want as the parent)

sinon, changez-le.

 UPDATE theme SET parent_id  = '[value]' WHERE theme_title = '[Theme name]';

then quit mysql;

 bin/magento setup:static-content:deploy 

ou

grunt clean:[theme] (For example:  grunt clean:blank)

grunt exec:[theme]

grunt less:[theme]
wwsiv2
la source