Richtige Methode zum Aktualisieren der Eltern eines Themas in Magento 2


14

In Magento 2 können Sie ein übergeordnetes Thema in der theme.xmlDatei eines Themas angeben .

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

Wenn Magento zum ersten Mal ein Thema sieht, verwendet es diesen Wert, um ein Thema parent_idin der themeTabelle festzulegen. Dies ist die Quelle der Wahrheit, wo die Eltern eines Themas sind.

Wenn Sie jedoch versuchen, diesen Wert zu ändern, nachdem ein Thema zum System hinzugefügt wurde, kann Magento die parent_idSpalte nicht aktualisieren , und instanziierte Magento\Theme\Model\ThemeObjekte haben weiterhin das ursprüngliche übergeordnete Thema. (Auch wenn Sie den Cache leeren.)

Ich kann das beheben, indem ich den parent_idWert manuell ändere - das scheint ein Hack zu sein. Wo wird parent_idnormalerweise im Kerncode von Magento festgelegt, und welche Benutzeraktionen lösen dies aus? Dh gibt es eine Möglichkeit, Magento mitzuteilen "Bitte lade dieses Thema neu"


2
Ja, ich habe das auch bemerkt und die einzige Möglichkeit, dies zu ändern, nachdem das Thema registriert wurde, besteht darin, die Datenbank direkt zu ändern. Möglicherweise ein Bug?
Gareth Daine

Antworten:


2

AKTUALISIERT AM 20160310

Fazit

Es wird immer entweder über updateTheme()oder aus der Sammlung (über DB) gesetzt, wenn SieappState->getMode() == AppState::MODE_PRODUCTION

Antworten

So beantworten Sie die Frage: Wie kann Magento die Datei theme.xml neu laden? Die Antwort lautet:

Stellen Sie den Anwendungszustand zu developerVerwendung SetEnv MAGE_MODE developerin .htaccess(oder nginx Äquivalent) und dann einloggen, um den Verwaltungsbereich (oder aktualisieren jede Admin Strecke) zu Trigger Magento\Theme\Model\Theme\Plugin\Registration::beforeDispatch().

Die Thementabelle in der Datenbank wird aufgrund von aktualisiert

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

Einzelheiten finden Sie in der folgenden Analyse.

Analyse

Wow, der Magento 2-Code scheint mir wirklich komplex zu sein. Hast du diese Funktion studiert beforeDispatch()die updateThemeData()aber nur aufruftif ($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);
        }
    }

Wahrscheinlich haben Sie diesen Code durchlaufen.

beforeDispatch()wird nur über Admin-Routen und nicht über Front-End-Routen aufgerufen. Hier ist eine Spur:

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

Eigentlich sehe ich beforeDispatch()Aufrufe, updateThemeData()die dieses Nugget enthalten:

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

Das scheint eigentlich (endlich) auf einen Konfigurations-XML-Pfad zu verweisen, $themeData->getParentTheme()->getFullPath()aber diese Funktion wird immer noch verwendet $themeData->getParentTheme(). Oh, ich denke, die Logik lautet ' Wenn ich ein registriertes Thema aktualisiere, das eine parentId in der Sammlung hat (über die DB), dann suche einen übergeordneten Pfad in der Konfiguration und aktualisiere die Sammlung '.Also vielleicht ist es das.

Ansonsten bin ich völlig ratlos, wie das in der Theme-Oberfläche deklarierte Magento\Theme\Model\Theme::getParentTheme()implementiert getParentId()wird. Sicher ist es keine Magie. Wie Sie sagen, muss es entweder aus der Datenbank über die Auflistung oder aus dem XML-Konfigurationspfad des Themas stammen (wenn es geändert wurde oder noch nicht definiert wurde), aber ich kann keine Definition von finden getParentId(). Vielleicht wird es ja immer per updateTheme()ODER aus der Sammlung (via DB) gesetzt wenn dein appState->getMode() == AppState::MODE_PRODUCTION.

Ich fand es nützlich, Informationen von innen heraus zu lesen, updateThemeData()indem ich eine Protokollausgabe hinzufügte:

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

Welches wird sich anmelden /var/log/debug.log. Wenn der Anwendungsstatus auf " developerIch kann sehen, dass die übergeordnete ID bei jeder Aktualisierung der Verwaltungsseite immer festgelegt wird, ob sie geändert wurde theme.xmloder nicht. Mit Anwendungsstatus wird productiondie Funktion nie ausgeführt, daher komme ich zu folgendem Schluss:

Es wird immer per updateTheme()ODER aus der Sammlung (via DB) gesetzt also schade wenn deinappState->getMode() == AppState::MODE_PRODUCTION

Ich denke, Sie sind wahrscheinlich alle im developerApp-Status. defaultDer App-Status wird updateThemeData()natürlich auch ausgelöst . Beim weiteren Debuggen habe ich den vollständigen Pfad des Themas für das übergeordnete Thema von Luma aufgezeichnet frontend/Magento/blank. Die Hauptstadt hat Mmich also vielleicht etwas überrascht, auf das man achten sollte.


0

Das Obige schien für mich nicht zu funktionieren, also habe ich mich für den Hack entschieden.

Hoffe es hilft jemandem.

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)

Wenn nicht, ändern Sie es.

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

then quit mysql;

 bin/magento setup:static-content:deploy 

oder

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

grunt exec:[theme]

grunt less:[theme]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.