具有條件模型和字段集的 Magento 2 模塊示例(第 2 部分)

已發表: 2019-12-16

在上一篇文章中,我們查看了允許我們在管理面板中創建具有界面的規則模型的代碼。 這是模塊的重要組成部分,如果你不學習如何在前端使用它,它本身就毫無用處。 因此,是時候弄清楚其中的規則和條件的重要性了。

任何驗證模型都會繼承有助於驗證對象的條件。 因此,基於此驗證檢查,我們可以執行某些活動。 在我們的示例中,我們將創建一個規則,允許定義購物車中是否存在 `heavy_weight` 屬性值等於 1 (true) 的商品。 如果找到這樣的物品,我們將顯示一個帶有以下消息的塊“您的購物車中有一些重量級物品,請聯繫我們討論送貨事宜。” 在購物車頁面。

*重要的是要了解我們加載規則模型的方式不會 100% 適合實際案例。 這是因為我們將巧妙地指定一個必須加載規則ID的規則。 在此基礎上,我們將使用購物車中的物品——送貨地址來驗證已知對象。 在未作為示例創建的模塊中,必須將規則對像作為特殊類加載,這將驗證它們與當前環境的兼容性,即商店、客戶及其組、時間、日期等.我們一定會在一系列進一步的相關文章中處理這個問題。 *

重要的旁注:

現在,該模塊的代碼可以在 github.com 的公共存儲庫中免費獲得。 因此,不再需要從我們的博客文章中復制粘貼代碼。 所有必需的代碼都可以在這裡方便地獲得。

首先,讓我們在管理面板中創建一個新規則,這將有助於查找屬性值指定為heavy_weight 的產品:

具有條件模型和字段集的 Magento 2 模塊示例(第 2 部分)| MageWorx 博客
具有條件模型和字段集的 Magento 2 模塊示例(第 2 部分)| MageWorx 博客

*如果您在條件的屬性列表中沒有看到您的屬性,請務必先檢查該屬性的配置。 應確保未禁用“用於促銷規則條件”選項。

為此,請轉到商店 > 屬性 > 產品。 然後,從列表中選擇您的屬性 > Storefront Properties >。 用於促銷規則條件必須設置為“是”。 請參閱下面的屏幕截圖以獲取更多詳細信息:

具有條件模型和字段集的 Magento 2 模塊示例(第 2 部分)| MageWorx 博客

我的規則的 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()` 方法。 在該方法中,指定了正確的規則(它將驗證我們的購物車)以及送貨地址(它將用於驗證)。

我們使用標準的前端功能獲得送貨地址,即通過從結帳會話中請求它。 我們使用基於 ID 的過濾器從集合中填充規則。 (正如我在本文開頭提到的,這不是最好的方法,只能作為一個例子。請務必以最適合您的方式描述獲取規則的方法)。 當我們的塊中有 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` 自己的方法添加到類規則中,無論是否調用父方法。

這是我們將在前端得到的結果:

*T1 Blue產品的heavy_weight屬性值為1:

![購物車中的有效產品]

具有條件模型和字段集的 Magento 2 模塊示例(第 2 部分)| MageWorx 博客

*T1 Red產品的heavy_weight屬性值為0:

![購物車中的有效產品]

具有條件模型和字段集的 Magento 2 模塊示例(第 2 部分)| MageWorx 博客

正如您在屏幕截圖中看到的那樣,我們來自區塊的消息顯示在購物車標籤下的 T1 Blue 產品上。 相反,對於紅色的,消息不會顯示。 這意味著該規則正常工作。


感謝大家花時間閱讀這篇文章。 如果您有任何問題,請隨時在下面的評論中分享。 我很樂意提供幫助。