마 젠토 2 : 인터랙션 전후 / 플러그인


32

Magento 2에서 "주변"플러그인을 만들 때

public function aroundRenderResult(
    \Magento\Framework\Controller\ResultInterface $subject,
    \Closure $proceed,
    ResponseHttp $response
) {
    //...
    $proceed($response);
    //...      
}    

전달 된 메소드 를 호출 / 호출하여 실제 원래 메소드를 호출하여 다음 단계의 플러그인으로 진행할 수 있습니다 $proceed. 이것은 일반적인 디자인 패턴이며, 종종 PHP 프레임 워크 미들웨어 구현에서 볼 수 있습니다.

그러나 구현 세부 사항에 혼란이 있습니다. 구체적으로

에 추가 aroundPlugin하여 객체 / 클래스에 before또는 after플러그인이 정의되어 있으면 언제 주변 플러그인 체인과 관련하여 실행됩니까?

즉, 모든 플러그인 메소드는 플러그인 메소드가 실행되기 전에 실행됩니까? 또는 의지 플러그인 전에 최종 실제 전에 화재 실제 방법 화재?

내가 추적하려고하는 특정 문제는 Magento 가 전체 페이지 캐싱 모드에있을 때 디스패치 방법에 Magento 2 전면 컨트롤러에 연결된 플러그인을 얻을 수없는 것 입니다. 전체 페이지 캐시는 호출 하지 않는 around 플러그인에 의해 작동합니다 $proceed($response). 나는이 플러그인 주위의 코드 중 일부를 파고 들었고 플러그인의 작동 방식을 모른 채 시스템이 추론하기가 어렵다는 것을 알았습니다.

, dev docs 페이지설명 이이 특정 인스턴스에서 정확하지 않은 것으로 나타납니다. 설명서가 잘못되었는지 또는 최근에 소개 된 버그인지, 엣지 케이스인지, 플러그인 구성이 잘못된 지 확실하지 않습니다.

누구든지, 직접 관찰 또는 문화 지식을 통해이 우선 순위 지정이 어떻게 작동해야하는지 알고 있습니까?


Alan, 플러그인에서 \closure $proceedvs. 를 사용할 때 경험할 규칙이 \callable $proceed있습니까? 공식 문서는 단지 언급 \callable과에 닿지 않게 \closure.
thdoan

답변:


38

플러그인은 정렬 순서에 따라 정렬 된 다음 메소드 접두어에 따라 정렬됩니다.

예 : 다음 메소드와 sortOrder를 갖는 3 개의 플러그인 (PluginA, PluginB, PluginC)이있는 메소드의 경우 :

  • 플러그인 A (sortOrder = 10)
    • beforeDispatch ()
    • afterDispatch ()
  • PluginB (sortOrder = 20)
    • beforeDispatch ()
    • aroundDispatch ()
    • afterDispatch ()
  • PluginC (sortOrder = 30) :
    • beforeDispatch ()
    • aroundDispatch ()
    • afterDispatch ()

실행 흐름은 다음과 같아야합니다.

  • PluginA :: beforeDispatch ()
  • PluginB :: beforeDispatch ()
  • PluginB :: aroundDispatch ()
    • PluginC :: beforeDispatch ()
    • PluginC :: aroundDispatch ()
      • 액션 :: 디스패치 ()
    • PluginC :: afterDispatch ()
  • PluginB :: afterDispatch ()
  • PluginA :: afterDispatch ()

16

Magento 2 요리 책에서 :

동일한 원래 기능을 확장하는 여러 플러그인이있는 경우 다음 순서로 실행됩니다.

  • 가장 낮은 이전 플러그인 sortOrder
  • 가장 낮은 주변 플러그인 sortOrder
  • 다른 플러그인 이전 (최저에서 최고로 sortOrder)
  • 플러그인 주변의 기타 (최저에서 최고로 sortOrder)
  • 가장 높은 애프터 플러그인 sortOrder
  • 플러그인 후 다른 것 (가장 높은 것부터 가장 낮은 것까지 sortOrder)

1

나를 위해 그것은 다음과 같이 작동해야합니다 :

  • 정렬 순서가 0과 동일하게 정의되지 않은 경우 (실제 순서가 정의되지 않았 음을 의미)
  • 플러그인은 순서대로 정렬되어야합니다

코드를 검토 \Magento\Framework\Interception\Interceptor::___callPlugins()하면 플러그인이 $pluginInfo변수 에 저장된 순서대로 호출 된 것을 볼 수 있습니다 . 이 정보는 다음과 같은 인터셉터에서 자동 생성 방법을 통과했습니다.

public function {method}()
{
    $pluginInfo = $this->pluginList->getNext($this->subjectType, '{method}');
    if (!$pluginInfo) {
        return parent::{method}();
    } else {
        return $this->___callPlugins('{method}', func_get_args(), $pluginInfo);
    }
}

플러그인 정렬을 담당하는 \Magento\Framework\Interception\PluginListInterface인터페이스 및 \Magento\Framework\Interception\PluginList\PluginList기본 구현 을 볼 수 있습니다 . _inheritPlugins : 152 메소드를 참조하십시오

/**
 * Sort items
 *
 * @param array $itemA
 * @param array $itemB
 * @return int
 */
protected function _sort($itemA, $itemB)
{
    if (isset($itemA['sortOrder'])) {
        if (isset($itemB['sortOrder'])) {
            return $itemA['sortOrder'] - $itemB['sortOrder'];
        }
        return $itemA['sortOrder'];
    } elseif (isset($itemB['sortOrder'])) {
        return $itemB['sortOrder'];
    } else {
        return 1;
    }
} 

나 에게이 기능에는 두 가지 논리적 오류가 있습니다.

  • return $itemB['sortOrder'];이어야한다 return - $itemB['sortOrder'];
  • return 1; 해야한다 return 0;

그것이 도움이되기를 바랍니다.


하지만 $ pluginInfo에 플러그인이 완전히로드되어 있습니까? 아니면 동작에 영향을 줄 수있는 게으른 로딩이 있습니까? 정렬 순서는 여러 플러그인에서 무엇을 의미합니까? 즉, "플러그인 1 이전, 플러그인 1 주변, 플러그인 1 이후, 플러그인 2 이전, 플러그인 2 주변, 플러그인 2 이전", "플러그인 1 이전", "플러그인 2 이전, 플러그인 1 주변, 플러그인 2 주변"등입니다. 코드는 나중에 보이는 것처럼 보이지만, 게으른 로딩 방식으로 플러그인 정보를 채우는 "getNext"이며, Magento가 재귀를 피하는 방법으로이 모든 것이 불분명하고 버그가 무엇인지 파악하기 어렵습니다. 기능은 무엇입니까?
Alan Storm

마 젠토 정렬 플러그인 클래스가 플러그인 메소드가 아닙니다.
KAndy

예를 들어, 새로운 아리아가로드되는 경우 플러그인 목록을 변경할 수 있습니다.
KAndy

"플러그인 메서드가 아닌 플러그인 클래스 정렬"로 플러그인 상호 작용 규칙이 무엇인지 또는 명확해야하는지 명확하지 않기 때문에 명확하지 않은 암시 적 지식이 있습니다.
Alan Storm

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.