마 젠토 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.