Magento 2でテーマの親を更新する正しい方法


14

Magento 2では、テーマのtheme.xmlファイルで親テーマを指定できます。

<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>

Magentoが初めてテーマを見ると、この値を使用parent_idしてthemeテーブルにaを設定します。これは、テーマの親がどこにいるかの真実の源です。

ただし、テーマをシステム追加した後にこの値変更しようとすると、Magentoはparent_id列の更新に失敗し、インスタンス化されたMagento\Theme\Model\Themeオブジェクトには元の親テーマが残ります。(キャッシュをクリアしても。)

parent_id値を手動で変更することでこれを修正できます-これはハックのようです。parent_id通常、Magentoのコアコードのどこに設定されていますか。また、これをトリガーするユーザーアクションは何ですか?すなわち、Magentoに「このテーマをリロードしてください」と伝える方法はありますか


2
はい、私もこれに気づきました、そして、テーマが登録された後にこれを修正するのを見つけた唯一の方法はデータベースを直接修正することです。おそらくバグですか?
ガレスデイネ

回答:


2

20160310に更新

結論

常にupdateTheme()、またはコレクションから(DBを介して)設定されます。appState->getMode() == AppState::MODE_PRODUCTION

回答

質問に答えるには、Magentoにtheme.xmlファイルをリロードさせる方法は何ですか答えは次のとおりです。

アプリケーションの状態をdeveloper使用SetEnv MAGE_MODE developer.htaccess(またはnginxに相当)に設定し、管理領域にログイン(または管理ルートを更新)してトリガーしますMagento\Theme\Model\Theme\Plugin\Registration::beforeDispatch()ます。

データベースのテーマテーブルは、次の理由により更新されます。

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

詳細については、以下の分析を参照してください。

分析

うわー、Magento 2コードは本当に複雑に思えます。あなたはこの機能を研究しているbeforeDispatch()呼び出すupdateThemeData()だけでなく、をif ($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);
        }
    }

おそらく、あなたはこのコードを通り抜けたでしょう。

beforeDispatch()は、管理ルートを介してのみ呼び出され、フロントエンドルートでは呼び出されません。トレースは次のとおりです。

#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))

実際、このナゲットを含むbeforeDispatch()呼び出しupdateThemeData()が表示されます。

//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());
            }
//...

実際には(最終的に)config XMLパスを参照しているように見えます$themeData->getParentTheme()->getFullPath()が、その関数はまだを使用してい$themeData->getParentTheme()ます。ああ、ロジックは「コレクションにparentIdを持つ登録済みテーマを(DB経由で)更新している場合、構成で親パスを検索してコレクションを更新する」と思います。おそらくこれがそうでしょう。

それ以外の場合、テーマインターフェースで宣言Magento\Theme\Model\Theme::getParentTheme()されている実装getParentId()については完全に紛失しています。確かに魔法ではありません。あなたが言うように、それはコレクションを介してDBから、またはテーマの設定XMLパス(変更されたかまだ定義されていない場合)のいずれかから来る必要がありますが、の定義を見つけることができませんgetParentId()。たぶんupdateTheme()、コレクションから(ORを介して)常に設定されるので、appState->getMode() == AppState::MODE_PRODUCTION

updateThemeData()ログ出力を追加して、内部から情報を収集すると便利です。

//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());
            }
//...

にログインし/var/log/debug.logます。アプリケーションの状態を「developer私」に設定すると、変更されたかどうかに関係なく、管理ページが更新されるたびに親IDが常に設定されますtheme.xml。アプリケーションの状態でproductionは、関数は決して実行されないので、私は結論づけます:

updateTheme()コレクションから(DB経由で)ORを介して常に設定されるため、appState->getMode() == AppState::MODE_PRODUCTION

おそらくdeveloperアプリの状態にあると思います。もちろん、defaultアプリの状態もトリガーされupdateThemeData()ます。さらにデバッグする際に、Lumaの親テーマのテーマの完全なパスを記録しましたfrontend/Magento/blank。首都Mは私を驚かせたので、たぶん気を付けなければならないことがある。


0

上記は私には役に立たないようでしたので、私はハックで行きました。

それが誰かを助けることを願っています。

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)

そうでない場合は、変更します。

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

then quit mysql;

 bin/magento setup:static-content:deploy 

または

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

grunt exec:[theme]

grunt less:[theme]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.