Пример модуля Magento 2 с моделью условий и набором полей (часть 2)
Опубликовано: 2019-12-16В предыдущей статье мы рассмотрели код, который позволяет нам создать модель правил с интерфейсом в панели администратора. Это была значительная часть модуля, которая сама по себе бесполезна, если вы не научитесь использовать ее во внешнем интерфейсе. Таким образом, самое время выяснить важность правил и условий в них.
Любая модель проверки наследует условия, которые помогают проверять объект. В результате на основе этой проверки мы можем выполнять определенные действия. В нашем примере мы создадим правило, которое позволяет определить, есть ли в корзине товар со значением атрибута `heavy_weight`, равным 1 (true). В случае, если такой товар будет найден, мы отобразим блок со следующим сообщением «В вашей корзине есть тяжеловесные товары, пожалуйста, свяжитесь с нами, чтобы обсудить доставку». на странице корзины.
*Очень важно понимать, что то, как мы загружаем нашу модель правил , не будет на 100% соответствовать реальному случаю. Это по той причине, что мы аккуратно укажем правило, с которым должен загружаться Rule ID . На его основе мы сверим известный объект с товарами из корзины—адресом доставки. В модуль, который не был создан в качестве примера, объекты Rules должны быть загружены как специальный класс, который будет проверять их на совместимость с текущей средой, т. е. магазином, покупателем и его группой, временем, датой и т. д. Мы обязательно коснемся этого вопроса в ряде других статей по теме. *
Важное примечание:
Сейчас код модуля находится в свободном доступе в публичном репозитории на github.com. Таким образом, больше не нужно копировать и вставлять код из наших сообщений в блоге. Весь необходимый код удобно доступен здесь.
Для начала создадим в админке новое правило, которое поможет найти товар со значением атрибута, указанным как heavy_weight:
*Если вы не видите свой атрибут в списке атрибутов в условиях, обязательно сначала проверьте конфигурацию этого атрибута. Это необходимо для того, чтобы для него не была отключена опция « Использовать для условий правила акции» .
Для этого перейдите в Магазины > Атрибуты > Продукт. Затем выберите свой атрибут из списка > Свойства витрины >. Использование для условий правила акции должно быть установлено как «Да». Пожалуйста, обратитесь к скриншоту ниже для более подробной информации:
У моего правила ID 1. В дальнейшем я буду использовать его для облегчения процесса загрузки. Теперь давайте обновим макет страницы корзины, добавив в нее наш новый блок, отображающий новое сообщение.
`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> ```
Как вы могли заметить из макета, нам понадобятся еще 2 файла: блок и шаблон. Создадим их:
`app/code/Vendor/Rules/view/frontend/templates/cart/example.phtml` ```php <?php /** @var \Vendor\Rules\Block\Cart\RuleExample $block */ ?> <?= $block->getMessage();?> ```
В шаблоне все сделано просто, т.е. только вывод сообщения. При необходимости вы можете добавить макет по мере необходимости.
Имейте в виду, что при использовании таких шаблонов на страницах полностраничного кэша результаты также будут кэшироваться. Для таких страниц следует использовать другой подход, подробно описанный в официальной документации Magento для разработчиков.
Пришло время добавить основной класс из примера. Вот класс блока:
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(); } } ```
Давайте немного остановимся на этом классе, так как именно в нем скрыта валидация. У него есть только один общедоступный метод, который мы используем в нашем шаблоне. Это метод `getMessage()`. Внутри метода указывается правильное правило (оно будет проверять нашу корзину), а также адрес доставки (он будет использоваться для проверки).
Мы получаем адрес доставки, используя стандартную функциональность веб-интерфейса, т. е. запрашивая его из сеанса оформления заказа. Мы заполняем правило из коллекции с помощью фильтра, основанного на идентификаторе. (Как я уже упоминал в начале этого поста, это не самое лучшее средство и может быть использовано исключительно в качестве примера. Обязательно опишите способ получения правила удобным для вас способом). Когда в нашем блоке есть 2 обязательных объекта, нам остается только проверить, что вернет метод `$rule->validate($shippingAddress)` нашего правила, т. е. true или false. По результатам создать (или нет) сообщение, которое будет отображаться на странице корзины в нашем шаблоне. Внутри модели правила это работает следующим образом:
```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); } ```
Этот метод уже существует в абстрактном классе Magento\Rule\Model\AbstractModel, от которого наследуются наши правила класса Vendor\Rules\Model\Rule. Если вам нужна пользовательская проверка, всегда можно добавить собственный метод `validate` в правила класса с вызовом родительского метода или без него.
Вот что мы получим в результате на фронтенде:
*Значение атрибута Heavy_weight продукта T1 Blue равно 1:
![Действительный товар в корзине]
*Значение атрибута Heavy_weight продукта T1 Red равно 0:
![Действительный товар в корзине]
Как видно на скриншотах, наше сообщение из блока отображается для товара T1 Blue под ярлыком корзины. Для красного, наоборот, сообщение не отображается. Это означает, что правило работает правильно.
Спасибо всем, что нашли время прочитать статью. Если у вас есть какие-либо вопросы, не стесняйтесь поделиться ими в комментариях ниже. Я буду рад помочь.