2. Magento: Etkileşimden önce / sonra / sonra Eklenti


32

Magento 2'de "etrafında" bir eklenti oluşturduğunuzda

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

Eğer yapabilirsiniz Devam geçirilen çağırarak / arayarak, çağrı gerçek orijinal yöntem ile sonuçlanan, bir sonraki etrafında eklentisi için $proceedyöntemle. Bu genellikle PHP Frameworks katman yazılım uygulamalarında görülen yaygın bir tasarım desenidir.

Bununla birlikte - uygulama detaylarına w / r / t bazı karışıklıklar sunar. özellikle

Bir aroundPluginnesneye ek olarak , bir nesnenin / sınıfın tanımlanmış bir beforeveya aftereklentisi varsa , bunlar ne zaman eklentiler zinciriyle ilişkili olarak ateşlenir?

yani, önceki tüm yöntemler, herhangi bir eklenti yöntemi etrafındakilerden önce ateşlenir mi? Yoksa eklentilerden önce, yalnızca gerçek, gerçek yöntem ateşlenmeden önce ateşlenir mi?

İzlemeye çalıştığım belirli sorun , Magento tam sayfa önbelleğe alma modundayken , gönderme yöntemine bir Magento 2 ön denetleyicisine eklenmiş bir eklenti bulamıyorum . Tam sayfa önbelleği, çağrı yapmayan bir eklenti ile çalışır $proceed($response). Bu eklentilerin etrafındaki bazı kodların içine girmeye çalıştım ve sistemin bu eklentilerin nasıl çalıştığını bilmeden nedenini zor buldum.

yani - dev docs sayfasındaki açıklama, bu özel örnekte yanlış görünüyor. Dokümantasyonun yanlış olup olmadığı veya bunun kısa süre önce ortaya konan bir hata olup olmadığı, uç bir dava olması veya eklenti konfigürasyonumun yanlış olup olmadığı açık değildir.

Doğrudan öncelikli gözlem ile veya kültürel bilgiyle, bu önceliklendirmenin nasıl çalışması gerektiğini bilen var mı?


Alan, kullanmak Pratik bir kural var mı \closure $proceedvs \callable $proceedbir eklenti? Resmi doc sadece bahseder \callableve üzerinde asla dokunmaz \closure.
Aralık'ta

Yanıtlar:


38

Eklentiler önce sıralama düzenine, ardından yöntem önekine göre sıralanır.

Örnek: 3 eklentili yöntem için (PluginA, PluginB, PluginC) ve aşağıdaki yöntemlerle sortOrder:

  • EklentiA (sortOrder = 10)
    • beforeDispatch ()
    • afterDispatch ()
  • EklentiB (sortOrder = 20)
    • beforeDispatch ()
    • aroundDispatch ()
    • afterDispatch ()
  • EklentiC (sortOrder = 30):
    • beforeDispatch ()
    • aroundDispatch ()
    • afterDispatch ()

Yürütme akışı aşağıdaki gibi olmalıdır:

  • PluginA :: beforeDispatch ()
  • PluginB :: beforeDispatch ()
  • PluginB :: aroundDispatch ()
    • PluginC :: beforeDispatch ()
    • PluginC :: aroundDispatch ()
      • Eylem :: gönderme ()
    • PluginC :: afterDispatch ()
  • PluginB :: afterDispatch ()
  • PluginA :: afterDispatch ()

16

Magento 2 yemek kitabından:

Aynı orijinal işlevi genişleten birden fazla eklenti varsa, bunlar aşağıdaki sırayla yürütülür:

  • en düşük eklenti öncesi sortOrder
  • en düşük olan eklenti sortOrder
  • eklentilerden önceki diğer (en alçaktan en yükseğe sortOrder)
  • eklentilerin etrafındaki diğer (en alçaktan en yükseğe sortOrder)
  • en yüksek olan eklenti sortOrder
  • diğer eklentilerden sonra (en yüksekten en düşüğe sortOrder)

1

Benim için şöyle çalışmalı:

  • Eğer sıralama düzeni sıfıra eşit değilse (ve bu, gerçek sıranın tanımsız olduğu anlamına gelir)
  • eklentileri sıraya göre sıralanmalıdır

Eğer kodunuzu gözden \Magento\Framework\Interception\Interceptor::___callPlugins()geçirirseniz, $pluginInfodeğişkenlerin depolanma sırasına göre adlandırılmış eklentileri görebilirsiniz . Bu bilgiler, örneğin

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

Gördüğünüz gibi eklenti sıralamadan \Magento\Framework\Interception\PluginListInterfacearayüz ve \Magento\Framework\Interception\PluginList\PluginListvarsayılan uygulama sorumludur. Bakınız _inheritPlugins: 152 yöntemi

/**
 * 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;
    }
} 

Benim için bu fonksiyonun iki mantıksal hatası var:

  • return $itemB['sortOrder'];olmalı return - $itemB['sortOrder'];
  • return 1; olmalı return 0;

Umarım size yardımcı olur.


ama $ pluginInfo tamamen eklentilerle yüklendi mi? Yoksa davranışı etkileyebilecek tembel bir yükleme var mı? Sıralama düzeni birden fazla eklenti için ne anlama geliyor? yani, "eklenti 1'den önce, eklenti 1 civarında, eklenti 1'den sonra, eklenti 2'den önce, eklenti 2'nin etrafında, eklenti 2'den sonra" veya "eklenti 1'den önce", "eklenti 2'den önce, eklenti 2'nin etrafında, eklenti 2'nin etrafında" Kod daha sonra gibi görünüyor, ancak "getNext" eklenti bilgilerini (belki?) Tembel bir yükleme biçiminde dolduruyor ve Magento'nun etrafta özyinelemeyi nasıl önlediğini nasıl belirsizleştirdiğini ve bir hatanın ne olduğunu bulmak zor, bir özellik nedir.
Alan Storm,

Magento sıralama eklentisi sınıf değil eklenti yöntemi.
KAndy

Eklentilerin listesi, örneğin, eğer yeni bir arya yüklenirse, değiştirilebilir.
KAndy

Belirgin olmayan bazı açık bilgiler var, çünkü "eklenti sınıfını sıralama ve eklenti yöntemi değil", eklenti etkileşimi için kuralların ne olduğunu veya olması gerektiğini açıkça belirtmiyor.
Alan Storm,

belki bu bağlantı faydalı olacaktır magehero.com/posts/472/magento-2-interception
KAndy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.