具有条件模型和字段集的 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 产品上。 相反,对于红色的,消息不会显示。 这意味着该规则正常工作。


感谢大家花时间阅读这篇文章。 如果您有任何问题,请随时在下面的评论中分享。 我很乐意提供帮助。