Exemplo do Módulo Magento 2 com Modelo de Condições e Fieldset (Parte 2)
Publicados: 2019-12-16No artigo anterior, vimos o código que nos permite criar um modelo de regras com uma interface no painel de administração. Essa foi uma parte significativa do módulo, que é inútil por si só se você não aprender a usá-lo no frontend. Assim, é hora de descobrir a importância das regras e condições dentro deles.
Qualquer modelo de validação herda condições que ajudam a validar um objeto. Como resultado, com base nessa verificação de validação, podemos realizar determinadas atividades. Em nosso exemplo, criaremos uma regra que permite definir se existe um item com o valor do atributo `heavy_weight` igual a 1 (true) no carrinho de compras. Caso tal item seja encontrado, exibiremos um bloco com a seguinte mensagem 'Você tem alguns itens pesados em seu carrinho, entre em contato conosco para discutir a entrega.' na página do carrinho de compras.
*É fundamental entender que a maneira como carregamos nosso modelo de regra não se encaixa 100% em um caso da vida real. Isso ocorre porque especificaremos claramente uma regra com a qual o ID da regra deve ser carregado. Com base nele, validaremos o objeto conhecido com os itens do carrinho – endereço de entrega. Em um módulo que não foi criado como exemplo, os objetos Rules devem ser carregados como uma classe especial, que os validará em relação à sua compatibilidade com o ambiente atual, ou seja, uma loja, um cliente e seu grupo, hora, data, etc. Certamente trataremos desse assunto em uma série de artigos relacionados. *
Nota lateral importante:
Agora, o código do módulo está disponível gratuitamente no repositório público no github.com. Assim, não há mais copiar e colar código de nossas postagens no blog. Todo o código necessário está convenientemente disponível aqui.
Primeiro, vamos criar uma nova regra no Painel Administrativo, que ajudará a encontrar um produto com o valor do atributo especificado como peso_pesado:
*Se você não vir seu atributo na lista de atributos em condições, verifique primeiro a configuração desse atributo. Isso deve ser feito para garantir que a opção Use For Promo Rule Conditions não esteja desabilitada para isso.
Para fazer isso, vá para Lojas > Atributos > Produto. Em seguida, selecione seu atributo na lista > Propriedades da vitrine >. As condições da regra de uso para promoção devem ser definidas como 'Sim'. Por favor, consulte a captura de tela abaixo para obter mais detalhes:
Minha regra tem ID 1. Além disso, vou usá-la para facilitar o processo de carregamento. Agora, vamos atualizar o layout da página do carrinho adicionando nosso novo bloco que exibe uma nova mensagem nele.
`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> ```
Como você deve ter notado pelo layout, precisaremos de mais 2 arquivos: um bloco e um modelo. Vamos criá-los:
`app/code/Vendor/Rules/view/frontend/templates/cart/example.phtml` ```php <?php /** @var \Vendor\Rules\Block\Cart\RuleExample $block */ ?> <?= $block->getMessage();?> ```
Tudo é simplificado no modelo, ou seja, apenas uma saída de mensagem. Se necessário, você pode adicionar um layout conforme necessário.
Lembre-se de que, ao usar esses modelos em páginas de cache de página inteira, os resultados também serão armazenados em cache. Uma abordagem diferente deve ser usada para essas páginas, que é descrita em detalhes nos documentos oficiais do Magento dev.
É hora de adicionar a classe principal do exemplo. Aqui está a classe do bloco:
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(); } } ```
Vamos nos debruçar um pouco sobre essa classe, pois é exatamente onde a validação está oculta. Ele tem apenas um método público que usamos em nosso modelo. É o método `getMessage()`. Dentro do método, é especificada uma regra correta (vai validar nosso carrinho), assim como o endereço de entrega (será usado para validação).
Obtemos o endereço de entrega usando a funcionalidade padrão do frontend, ou seja, solicitando-o na sessão de checkout. Preenchemos a regra da coleção usando um filtro baseado no ID. (Como mencionei no início deste post, não é o melhor meio e pode ser usado apenas como exemplo. Certifique-se de descrever o método de obter a regra da maneira que melhor lhe convier). Ao ter 2 objetos obrigatórios em nosso bloco, resta apenas verificar o que o método `$rule->validate($shippingAddress)` da nossa regra irá retornar, ou seja, true ou false. Com base nos resultados, crie (ou não) uma mensagem que será exibida na página do carrinho em nosso template. Dentro do modelo de regras, funciona da seguinte forma:
```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); } ```
Este método já existe na classe abstrata `Magento\Rule\Model\AbstractModel`, da qual nossas regras de classe `Vendor\Rules\Model\Rule` são herdadas. Se você precisar de validação personalizada, sempre é possível adicionar o próprio método `validate` às regras de classe com ou sem invocar um método pai.
Aqui está o que obteremos como resultado no frontend:
*O valor do atributo heavy_weight do produto T1 Blue é igual a 1:
![Produto válido em um carrinho]
*O valor do atributo heavy_weight do produto T1 Red é igual a 0:
![Produto válido em um carrinho]
Como você pode ver nas capturas de tela, nossa mensagem do bloco é exibida para o produto T1 Blue sob o rótulo do carrinho. Para o vermelho, inversamente, a mensagem não é exibida. Isso significa que a regra funciona corretamente.
Obrigado a todos por dedicarem um tempo para ler o artigo. Se você tiver alguma dúvida, sinta-se à vontade para compartilhá-la nos comentários abaixo. Ficarei feliz em ajudar.