Neste tutorial, vamos dar uma olhada no Quote (carrinho) do Magento 2. Vamos entender o seu processo inicial e pegar as informações que estão no carrinho de maneira prática, rápida e usando boas práticas.
Mas, por que isso? Bom, temos diversas soluções vistas na internet, porém muitas delas são prejudiciais para a performance do checkout, fazendo load do objeto Quote, por exemplo, que é o pesadíssimo objeto do carrinho, usando o Object Manager e entre outras. O objetivo desse artigo é explicar o funcionamento do Magento 2 quando é adicionado produtos ao carrinho e como pegar essas informações de maneira correta.
Há dois pontos importantes que precisamos entender quando falamos de Quote e como pegar a informações que estão nele.
Banco de Dados
Compreender a maneira como o Magento 2 armazenar as informações do Quote no banco de dados é muito importante.
Vamos considerar duas tabelas: quote
e quote_item
Quando adicionamos um produto no carrinho de compras o Magento 2 cria uma sessão no checkout e uma linha na tabela quote
Na imagem acima, mostramos um exemplo claro disso. Ao adicionar um produto ao carrinho de compras uma linha foi criada para efetuar a administração da sessão do checkout iniciada. Para este artigo, a informação mais importante para nós será o entity_id
.
Em seguida, é adicionado uma nova linha na tabela quote_item. Nela será armazenada as informações do produto adicionado ao carrinho.
Como na imagem acima, três produtos foram adicionados ao carrinho, tendo uma linha na tabela para cada produto, onde podemos ver várias informações deles, como: name, sku, product_id e etc. Note que temos a chave estrangeira quote_id
que é a nossa entity_id da tabela quote.
Dessa maneira, entendemos o funcionamento básico de como o Magento adiciona os produtos no carrinho de compras e gerencia as informações deles.
Collection Factory
O Magento 2 trabalha com factories para pegar as informações que estão no banco de dados.
vendor/magento/module-quote/Model/ResourceModel/Quote/Item.php
No arquivo acima, temos o seguinte método:
protected function _construct() { $this->_init('quote_item', 'item_id'); }
Sempre que vemos o método _init()
numa model sabemos que ela faz conexão com o banco de dados. Nesse próprio método, conseguimos saber com qual tabela ele está trabalhando: quote_item
vendor/magento/module-quote/Model/ResourceModel/Quote/Item/Collection.php
No arquivo acima, podemos ver o método:
protected function _construct() { $this->_init(QuoteItem::class, ResourceQuoteItem::class); }
No _init() não temos a informação da tabela, mas a classe que já está sem comunicando com ela, conforme visto anteriormente.
O que isso nos tem a dizer?
O Magento 2 trabalha com o Design Patterns Factories. E cria uma factory, fábrica, pra a partir disso, termos uma collection com todas as informações que precisamos da nossa tabela quote_item.
Tendo esse entedimento, vamos ao nosso trabalho. O que faremos? Vamos pegar as informações dos produtos do nosso carrinho de compras.
Para esse artigo, criamos um pequeno módulo onde nós exibiremos os produtos que estão no carrinho de compras em um rota customizada:
Primeiro, a nossa model com as regras pra pegar as informações do carrinho:
<?php namespace AbraaoMarques\Quote\Model; use Magento\Quote\Model\ResourceModel\Quote\Item\CollectionFactory; use Magento\Checkout\Model\Session; class Product { private $_collectionFactory; private $_checkoutSession; public function __construct( CollectionFactory $collectionFactory, Session $checkoutSession ) { $this->_collectionFactory = $collectionFactory; $this->_checkoutSession = $checkoutSession; } private function getQuoteId() { return $this->_checkoutSession->getQuoteId(); } public function getAllProducts() { $factory = $this->_collectionFactory->create(); $collection = $factory->addFieldToSelect('name') ->addFieldToSelect('sku') ->addFieldToSelect('product_id') ->addFieldToFilter('quote_id', $this->getQuoteId()) ->getData(); return $collection; } }
Explicando:
use Magento\Quote\Model\ResourceModel\Quote\Item\CollectionFactory; use Magento\Checkout\Model\Session;
O use em CollectionFactory nos possibilita criar a nossa factory para criarmos a nossa collection de dados
O use em Session nos possibilidade pegar as informações da sessão do checkout que foi criada pela Magento 2. A informação que precisamos obter, neste caso, é o quote_id.
No nosso método getQuoteId()
retornamos o quote_id da sessão ativa.
private function getQuoteId() { return $this->_checkoutSession->getQuoteId(); }
No nosso método getAllProducts()
criamos a nossa collection, a partir da factory, e pegamos as informações dos produtos como name, sku e product_id usando o quote_id como filtro:
public function getAllProducts() { $factory = $this->_collectionFactory->create(); $collection = $factory->addFieldToSelect('name') ->addFieldToSelect('sku') ->addFieldToSelect('product_id') ->addFieldToFilter('quote_id', $this->getQuoteId()) ->getData(); return $collection; }
No nosso controller temos:
<?php namespace AbraaoMarques\Quote\Controller\Quote; use Magento\Framework\App\Action\Action; use Magento\Framework\App\Action\Context; use AbraaoMarques\Quote\Model\Product; class Products extends Action { private $_product; public function __construct( Context $context, Product $product ) { parent::__construct($context); $this->_product = $product; } /** * Execute action based on request and return result * * Note: Request will be added as operation argument in future * * @return \Magento\Framework\Controller\ResultInterface|ResponseInterface * @throws \Magento\Framework\Exception\NotFoundException */ public function execute() { $products = $this->_product->getAllProducts(); var_dump('<pre>',$products); } }
Fazemos um USE da nossa model e, no método execute()
do nosso controller, chamamos o método getAllProducts()
e damos um var_dump()
na variável $products
.
Feito isso, acessando a nossa rota customizada temos:
Uma dica sobre collection:
Caso queira trazer todas as informações da tabela, use o * (asterisco) no método addFieldToSelect()
:
public function getAllProducts() { $factory = $this->_collectionFactory->create(); $collection = $factory->addFieldToSelect('*') ->addFieldToFilter('quote_id', $this->getQuoteId()) ->getData(); return $collection; }
Espero ter ajudado!
Dúvidas? Posta aí!!!
Aquele abraço!!!
Excelente explicação obrigado pelas informações
😀