Przykład modułu Magento 2 z modelem warunków i zestawem pól (część 2)
Opublikowany: 2019-12-16W poprzednim artykule przyjrzeliśmy się kodowi, który pozwala nam stworzyć model Reguł z interfejsem w Panelu Administracyjnym. To była znacząca część modułu, który sam w sobie jest bezużyteczny, jeśli nie nauczysz się go używać na interfejsie. Dlatego nadszedł czas, aby dowiedzieć się, jak ważne są w nich reguły i warunki.
Każdy model walidacji dziedziczy warunki, które pomagają w walidacji obiektu. W rezultacie na podstawie tej kontroli walidacyjnej możemy wykonać określone czynności. W naszym przykładzie utworzymy regułę, która pozwoli określić, czy w koszyku znajduje się produkt z wartością atrybutu `heavy_weight` równą 1 (prawda). Jeśli taki przedmiot zostanie znaleziony, wyświetlimy blok z następującą wiadomością „Masz w koszyku kilka ciężkich przedmiotów, skontaktuj się z nami, aby omówić dostawę”. na stronie koszyka.
*Bardzo ważne jest, aby zrozumieć, że sposób, w jaki ładujemy nasz model reguł , nie pasuje w 100% do rzeczywistego przypadku. Jest to powód, dla którego ładnie określimy regułę, którą musi zostać załadowany identyfikator reguły . Na tej podstawie potwierdzimy znany obiekt z pozycjami z koszyka―adresem wysyłki. W module, który nie został stworzony jako przykład, obiekty Rules muszą być wczytane jako specjalna klasa, która zweryfikuje je pod kątem ich zgodności z aktualnym środowiskiem tj. sklep, klient i jego grupa, godzina, data itp. Z pewnością zajmiemy się tą sprawą w serii kolejnych powiązanych artykułów. *
Ważna uwaga dodatkowa:
Teraz kod modułu jest bezpłatnie dostępny w publicznym repozytorium na github.com. W ten sposób nie trzeba już kopiować i wklejać kodu z naszych postów na blogu. Cały wymagany kod jest wygodnie dostępny tutaj.
Najpierw utwórzmy nową regułę w panelu administracyjnym, która pomoże znaleźć produkt z wartością atrybutu określoną jako heavy_weight:
*Jeśli nie widzisz swojego atrybutu na liście atrybutów w warunkach, najpierw sprawdź konfigurację tego atrybutu. Należy to zrobić, aby opcja Użyj dla warunków reguły promocji nie została dla niego wyłączona.
Aby to zrobić, przejdź do Sklepy > Atrybuty > Produkt. Następnie wybierz swój atrybut z listy > Właściwości witryny sklepowej >. Opcja „Użyj w warunkach promocji” musi być ustawiona na „Tak”. Proszę zapoznać się z poniższym zrzutem ekranu, aby uzyskać więcej informacji:
Moja reguła ma ID 1. Ponadto użyję go, aby ułatwić proces ładowania. Teraz zaktualizujmy układ strony koszyka, dodając nasz nowy blok, który wyświetla do niego nową wiadomość.
`app/code/Vendor/Rules/view/frontend/layout/checkout_cart_index.xml` ```xml <?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="checkout.cart.form.before"> <block class="Vendor\Rules\Block\Cart\RuleExample" name="custom_block_with_rules" template="Vendor_Rules::cart/example.phtml"/> </referenceContainer> </body> </page> ```
Jak mogłeś zauważyć z układu, będziemy potrzebować jeszcze 2 plików: bloku i szablonu. Stwórzmy je:
`app/code/Vendor/Rules/view/frontend/templates/cart/example.phtml` ```php <?php /** @var \Vendor\Rules\Block\Cart\RuleExample $block */ ?> <?= $block->getMessage();?> ```
Wszystko jest proste w szablonie, tj. po prostu wyjście wiadomości. W razie potrzeby możesz dodać układ zgodnie z potrzebami.
Pamiętaj, że korzystając z takich szablonów na pełnostronicowych stronach pamięci podręcznej, wyniki również zostaną zapisane w pamięci podręcznej. W przypadku takich stron należy zastosować inne podejście, które jest szczegółowo opisane w oficjalnych dokumentach deweloperskich Magento.
Czas dodać główną klasę z przykładu. Oto klasa bloku:
heckout\Model\Session as CheckoutSession; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\View\Element\Template; use Magento\Quote\Model\Quote\Address as QuoteAddress; use Vendor\Rules\Model\Rule; use Vendor\Rules\Model\ResourceModel\Rule\CollectionFactory as RulesCollectionFactory; /** * Class RuleExample */ class RuleExample extends Template { /** * @var RulesCollectionFactory */ private $rulesCollectionFactory; /** * @var string */ private $message; /** * @var CheckoutSession */ private $checkoutSession; /** * RuleExample constructor. * * @param Template\Context $context * @param RulesCollectionFactory $rulesCollectionFactory * @param CheckoutSession $checkoutSession * @param array $data */ public function __construct( Template\Context $context, RulesCollectionFactory $rulesCollectionFactory, CheckoutSession $checkoutSession, array $data = [] ) { $this->rulesCollectionFactory = $rulesCollectionFactory; $this->checkoutSession = $checkoutSession; $this->message = ''; parent::__construct($context, $data); } /** * @return string */ public function getMessage(): string { if ($this->message) { return $this->message; } $shippingAddress = $this->getShippingAddress(); if (!$shippingAddress) { return $this->message; } $rule = $this->getRule(); if ($rule && $rule->validate($shippingAddress)) { $this->message = __( 'You have some heavy weight items in your cart, please contact us to discuss delivery.' ); } return $this->message; } /** * @return Rule|null */ private function getRule(): ?Rule { /** @var \Vendor\Rules\Model\ResourceModel\Rule\Collection $rulesCollection */ $rulesCollection = $this->rulesCollectionFactory->create(); $rulesCollection->addFilter('rule_id', 1); /** @var Rule|null $rule */ $rule = $rulesCollection->getFirstItem(); return $rule; } /** * @return QuoteAddress|null */ private function getShippingAddress(): ?QuoteAddress { /** @var \Magento\Quote\Model\Quote $quote */ try { $quote = $this->checkoutSession->getQuote(); } catch (LocalizedException $exception) { return null; } if (!$quote) { return null; } return $quote->getIsVirtual() ? $quote->getBillingAddress() : $quote->getShippingAddress(); } } ```
Zastanówmy się trochę nad tą klasą, ponieważ właśnie tam ukryta jest walidacja. Ma tylko jedną publiczną metodę, której używamy w naszym szablonie. Jest to metoda `getMessage()`. Wewnątrz metody określana jest poprawna reguła (będzie ona walidować nasz koszyk), a także adres wysyłki (będzie użyty do walidacji).
Adres wysyłkowy otrzymujemy za pomocą standardowej funkcjonalności frontendu, tj. żądając go z sesji kasowej. Wypełniamy regułę z kolekcji za pomocą filtra opartego na identyfikatorze. (Jak wspomniałem na początku tego postu, nie jest to najlepszy sposób i można go używać wyłącznie jako przykładu. Pamiętaj, aby opisać metodę uzyskania reguły w sposób, który najbardziej Ci odpowiada). Mając 2 obowiązkowe obiekty w naszym bloku, pozostaje nam tylko sprawdzić, co zwróci metoda `$rule->validate($shippingAddress)` naszej reguły, czyli prawda czy fałsz. Na podstawie wyników utwórz (lub nie) wiadomość, która będzie wyświetlana na stronie koszyka w naszym szablonie. Wewnątrz modelu reguł działa to w następujący sposób:
```php /** * Validate rule conditions to determine if rule can run * * @param \Magento\Framework\DataObject $object * @return bool */ public function validate(\Magento\Framework\DataObject $object) { return $this->getConditions()->validate($object); } ```
Ta metoda istnieje już w klasie abstrakcyjnej `Magento\Rule\Model\AbstractModel`, z której dziedziczone są nasze reguły klasy `Vendor\Rules\Model\Rule`. Jeśli potrzebujesz niestandardowej walidacji, zawsze możesz dodać własną metodę `validate` do reguł klasy z lub bez wywoływania metody nadrzędnej.
Oto, co otrzymamy w wyniku na interfejsie użytkownika:
*Wartość atrybutu heavy_weight produktu T1 Blue wynosi 1:
![Prawidłowy produkt w koszyku]
*Wartość atrybutu heavy_weight produktu T1 Red wynosi 0:
![Prawidłowy produkt w koszyku]
Jak widać na zrzutach ekranu, nasza wiadomość z bloku wyświetla się dla produktu T1 Blue pod etykietą koszyka. W przypadku czerwonego odwrotnie, wiadomość nie jest wyświetlana. Oznacza to, że reguła działa poprawnie.
Dziękuję wszystkim za poświęcenie czasu na przeczytanie artykułu. Jeśli masz jakieś pytania, podziel się nimi w komentarzach poniżej. Chętnie pomogę.