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
네, 이것도 눈치 the습니다. 테마가 등록 된 후 이것을 수정하는 유일한 방법은 데이터베이스를 직접 수정하는 것입니다. 아마도 버그?
Gareth Daine

답변:


2

20160310에 업데이트 됨

결론

이 경우 항상 updateTheme()컬렉션을 통해 또는 컬렉션을 통해 (DB를 통해) 설정됩니다.appState->getMode() == AppState::MODE_PRODUCTION

대답

질문에 대답하려면 theme.xml 파일을 다시로드 젠토을 얻을 수있는 방법은 무엇 대답입니다 :

응용 프로그램 상태를 in (또는 nginx와 동등한) developer사용 SetEnv MAGE_MODE developer으로 설정 한 .htaccess다음 관리 영역에 로그인하거나 모든 관리 경로를 새로 고쳐 트리거하십시오 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(). 오, 나는 논리가 ' DB를 통해 컬렉션에 parentId가있는 등록 된 테마를 업데이트하는 경우 구성에서 부모 경로를 찾고 컬렉션을 업데이트합니다 '라고 생각합니다.아마이게 다야.

그렇지 않으면 테마 인터페이스에서 선언 된 Magento\Theme\Model\Theme::getParentTheme()구현 방법에 대해 완전히 손실되었습니다 getParentId(). 확실히 마술이 아닙니다. 당신이 말한 것처럼 컬렉션을 통해 DB에서 또는 테마의 구성 XML 경로 (변경되거나 아직 정의되지 않은 경우)에서 가져와야하지만의 정의를 찾을 수 없습니다 getParentId(). 어쩌면 그것은 항상 updateTheme()컬렉션을 통해 OR (DB를 통해)을 통해 너무 너무 설정되어있을 수도 있습니다 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가 변경 여부에 관계없이 항상 모든 관리자 페이지를 새로 고칠 때마다 부모 ID가 설정되어 있음을 알 수 있습니다 theme.xml. 응용 프로그램 상태 production에서는 함수가 실행되지 않으므로 결론을 내립니다.

updateTheme()컬렉션에서 OR을 통해 설정 (DB를 통해)하므로 너무 나쁘면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.