Modo corretto per aggiornare un genitore di un tema in Magento 2


14

In Magento 2, puoi specificare un tema principale nel theme.xmlfile di un 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>

La prima volta che Magento vede un tema, usa questo valore per impostare un parent_idnella themetabella. Questa è la fonte della verità per dove si trova il genitore di un tema.

Tuttavia, se si tenta di modificare questo valore dopo che un tema è stato aggiunto al sistema , Magento non riesce ad aggiornare la parent_idcolonna e gli Magento\Theme\Model\Themeoggetti istanziati avranno comunque il tema principale originale. (Anche se si cancella la cache.)

Posso risolvere questo problema modificando manualmente il parent_idvalore - sembra un hack. Dove si trova parent_idnormalmente il codice di base di Magento e quali azioni dell'utente attivano ciò? cioè c'è un modo per dire a Magento "ricaricare questo tema"


2
Sì, l'ho notato anche io e l'unico modo in cui ho scoperto di modificarlo dopo aver registrato il tema è modificare direttamente il database. Forse un bug?
Gareth Daine,

Risposte:


2

AGGIORNATO AL 20160310

Conclusione

È sempre impostato tramite updateTheme()o dalla raccolta (tramite DB) se il tuoappState->getMode() == AppState::MODE_PRODUCTION

Risposta

Per rispondere alla domanda Qual è il modo per ottenere Magento per ricaricare il file theme.xml la risposta è:

Impostare lo stato dell'applicazione su developerusing SetEnv MAGE_MODE developerin .htaccess(o nginx equivalente) e quindi accedere all'area admin (o aggiornare qualsiasi route admin) per eseguire il trigger Magento\Theme\Model\Theme\Plugin\Registration::beforeDispatch().

La tabella dei temi nel database è stata aggiornata a causa di

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

Vedi analisi sotto per i dettagli.

Analisi

Wow, il codice Magento 2 mi sembra davvero complesso. Hai studiato questa funzione beforeDispatch()che chiama updateThemeData()ma soloif ($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);
        }
    }

Probabilmente hai passato questo codice.

beforeDispatch()viene chiamato solo tramite route di amministrazione e non su route front-end. Ecco una traccia:

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

In realtà vedo beforeDispatch()chiamate updateThemeData()che contengono questo 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());
            }
//...

Che sembra effettivamente (finalmente) fare riferimento a un percorso XML di configurazione, $themeData->getParentTheme()->getFullPath()ma quella funzione utilizza ancora $themeData->getParentTheme(). Oh, penso che la logica sia ' Se sto aggiornando un tema registrato che ha un parentId nella raccolta (tramite il DB), quindi cerca un percorso principale nella configurazione e aggiorna la raccolta ".Quindi forse è così.

In caso contrario, sono totalmente a corto di Magento\Theme\Model\Theme::getParentTheme()attrezzi implementati getParentId()dichiarati nell'interfaccia del tema. Sicuramente non è magico. Come dici tu, deve provenire dal DB tramite la raccolta o dal percorso XML di configurazione del tema (se è cambiato o non è ancora definito) ma non riesco a trovare una definizione di getParentId(). Forse è sempre impostato tramite updateTheme()OR dalla raccolta (tramite DB), quindi troppo male se il tuo appState->getMode() == AppState::MODE_PRODUCTION.

Ho trovato utile raccogliere informazioni dall'interno updateThemeData()aggiungendo un output di registro:

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

Che accederà a /var/log/debug.log. Con lo stato dell'applicazione impostato su developerVedo che l'ID padre è sempre impostato su ogni aggiornamento della pagina di amministrazione, indipendentemente dal fatto che sia stato modificato theme.xmlo meno. Con lo stato dell'applicazione productionla funzione non viene mai eseguita, quindi concludo:

È sempre impostato tramite updateTheme()OR dalla raccolta (tramite DB), quindi è un peccato se il tuoappState->getMode() == AppState::MODE_PRODUCTION

Penso che probabilmente sei tutti nello developerstato dell'app. defaultlo stato dell'app si attiverà updateThemeData()anche ovviamente. Nell'ulteriore debug ho registrato il percorso completo del tema per il tema principale di Luma che era frontend/Magento/blank. La capitale Mmi ha sorpreso, quindi forse qualcosa a cui fare attenzione.


0

Quanto sopra non sembra funzionare per me, quindi sono andato con l'hacking.

Spero che aiuti qualcuno.

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)

se non lo è, cambiarlo.

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

then quit mysql;

 bin/magento setup:static-content:deploy 

o

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

grunt exec:[theme]

grunt less:[theme]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.