Cara yang benar untuk Memperbarui Induk Tema di Magento 2

14

Di Magento 2, Anda dapat menentukan tema induk di theme.xmlfile tema .

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

Pertama kali Magento melihat sebuah tema, ia menggunakan nilai ini untuk mengatur parent_iddalam themetabel. Ini adalah sumber kebenaran di mana orangtua tema berada.

Namun, jika Anda mencoba untuk mengubah nilai ini setelah tema ditambahkan ke sistem , Magento gagal memperbaruiparent_id kolom, dan Magento\Theme\Model\Themeobjek instantiated masih akan memiliki tema induk asli. (Bahkan jika Anda menghapus cache.)

Saya dapat memperbaikinya dengan mengubah parent_idnilai secara manual - yang tampaknya seperti peretasan. Di mana parent_idbiasanya diatur dalam kode inti Magento, dan tindakan pengguna apa yang memicu ini? yaitu apakah ada cara untuk memberi tahu Magento "tolong muat ulang tema ini"

Alan Storm
sumber
2
Ya, saya telah memperhatikan ini juga dan satu-satunya cara saya telah menemukan untuk memodifikasi ini setelah tema telah terdaftar adalah untuk memodifikasi database secara langsung. Mungkin bug?
Gareth Daine

Jawaban:

2

DIPERBARUI DI 20160310

Kesimpulan

Itu selalu diatur baik melalui updateTheme()atau dari koleksi (via DB) jika AndaappState->getMode() == AppState::MODE_PRODUCTION

Menjawab

Untuk menjawab pertanyaan Apa cara agar Magento memuat ulang file theme.xml jawabannya adalah:

Tetapkan status aplikasi untuk developermenggunakan SetEnv MAGE_MODE developerdalam .htaccess(atau setara nginx) dan kemudian masuk ke area admin (atau segarkan rute admin apa saja) untuk memicuMagento\Theme\Model\Theme\Plugin\Registration::beforeDispatch() .

Tabel tema dalam database diperbarui karena

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

Lihat analisis di bawah untuk detailnya.

Analisis

Wow kode Magento 2 sepertinya sangat rumit bagi saya. Sudahkah Anda mempelajari fungsi ini beforeDispatch()yang memanggil updateThemeData()tetapi hanyaif ($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);
        }
    }

Mungkin Anda telah melewati kode ini.

beforeDispatch()dipanggil hanya melalui rute admin dan bukan pada rute front-end. Berikut ini adalah jejaknya:

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

Sebenarnya saya melihat beforeDispatch()panggilan updateThemeData()yang berisi nugget ini:

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

Yang tampaknya sebenarnya (akhirnya) merujuk ke path XML config $themeData->getParentTheme()->getFullPath()tetapi fungsi itu masih menggunakan $themeData->getParentTheme(). Oh, saya pikir logikanya adalah ' Jika saya memperbarui tema terdaftar yang memiliki parentId dalam koleksi (melalui DB) kemudian mencari jalur induk di konfigurasi dan memperbarui koleksi '.Jadi mungkin ini dia.

Kalau tidak, saya benar-benar bingung bagaimana Magento\Theme\Model\Theme::getParentTheme()mengimplementasikan getParentId()yang dinyatakan dalam antarmuka tema. Tentunya itu bukan sihir. Seperti yang Anda katakan itu harus berasal dari DB melalui koleksi atau dari jalur XML konfigurasi tema (jika itu berubah atau belum didefinisikan) tetapi saya tidak dapat menemukan definisi getParentId(). Mungkin itu selalu diatur melalui updateTheme()ATAU dari koleksi (via DB) jadi terlalu buruk jika AndaappState->getMode() == AppState::MODE_PRODUCTION .

Saya merasa bermanfaat untuk mendapatkan informasi dari dalam updateThemeData()dengan menambahkan beberapa keluaran log:

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

Yang akan masuk /var/log/debug.log. Dengan status aplikasi diatur ke developerSaya dapat melihat ID induk selalu diset pada setiap halaman admin menyegarkan apakah itu diubah theme.xmlatau tidak. Dengan status aplikasiproduction , fungsi tidak pernah berjalan jadi saya menyimpulkan:

Itu selalu diatur melalui updateTheme()ATAU dari koleksi (via DB) jadi terlalu buruk jika AndaappState->getMode() == AppState::MODE_PRODUCTION

Saya pikir Anda semua mungkin dalam developerkeadaan aplikasi. defaultkeadaan aplikasi akan memicu updateThemeData()juga tentu saja. Dalam debugging lebih lanjut saya login path tema lengkap untuk tema induk Luma yang frontend/Magento/blank. Ibukota Mmengejutkan saya jadi mungkin sesuatu yang harus diwaspadai.

Malachy
sumber
0

Tampaknya hal di atas tidak berhasil bagi saya, jadi saya melakukan peretasan.

Semoga ini bisa membantu seseorang.

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)

jika tidak, ubahlah.

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

then quit mysql;

 bin/magento setup:static-content:deploy 

atau

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

grunt exec:[theme]

grunt less:[theme]
wwsiv2
sumber