Правильний спосіб оновлення батька теми в 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таблиці. Це джерело істини, де знаходиться батько теми.

Однак якщо ви спробуєте змінити це значення після того, як тема була додана в систему , Magento не вдалося оновити parent_idстовпчик, і екземпляри Magento\Theme\Model\Themeоб'єктів все ще матимуть початкову батьківську тему. (Навіть якщо ви очистите кеш.)

Я можу це виправити, вручну змінивши parent_idзначення - це здається злому. Де parent_idзазвичай встановлено основний код Magento, і які дії користувача викликають це? тобто є спосіб сказати Magento "будь ласка, перезавантажте цю тему"


2
Так, я теж помітив це, і єдиний спосіб, коли я виявив це змінити після того, як тема була зареєстрована, - це безпосередньо змінювати базу даних. Можливо, помилка?
Гарет Дайн

Відповіді:


2

ОНОВЛЕНО В 20160310

Висновок

Він завжди встановлюється через updateTheme()або з колекції (через БД), якщо ваш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());
            }
//...

Що, здається, насправді (нарешті) посилається на конфігураційний шлях XML, $themeData->getParentTheme()->getFullPath()але ця функція все ще використовується $themeData->getParentTheme(). О, я думаю, що логіка полягає в тому, що " Якщо я оновлюю зареєстровану тему, яка має parentId у колекції (через БД), то шукаю батьківський шлях у конфігурації та оновлюю колекцію ".То, можливо, це все.

Інакше я переживаю повну втрату щодо того, як Magento\Theme\Model\Theme::getParentTheme()реалізує, getParentId()що оголошено в інтерфейсі теми. Звичайно, це не магія. Як ви кажете, він повинен надходити або з БД через колекцію, або з конфігураційного шляху XML теми (якщо він змінився або ще не визначений), але я не можу знайти визначення getParentId(). Можливо, це завжди встановлено через updateTheme()АБО з колекції (через БД), так шкода, якщо ваша 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Я можу бачити, що батьківський ідентифікатор завжди встановлений на кожній сторінці адміністратора, оновіть, змінили його theme.xmlчи ні. Зі станом productionпрограми функція ніколи не запускається, тому я роблю висновок:

Він завжди встановлюється через updateTheme()АБО із колекції (через БД), настільки погано, якщо ваш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]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.