Cursos Magento

Como usar o Repository Pattern no Magento 2

,

Atualizado em 24 de agosto de 2022

A melhor forma de carregar entidades no Magento 2 é através do uso de Repository.

Neste tutorial veremos como o novo design pattern pode ser usado e como ele foi introduzido ao Magento 2. Ao longo deste artigo você verá:

  • O que são os repositórios no Magento 2
  • Exemplo de uso de Dependency Injection (Injeção de dependências)
  • Como pegar todos os produtos no Magento 2
  • Como filtrar, ordenar, e paginar ou limitar estes resultados
  • Como usar o SearchCriteriaBuilder no Magento 2

Repositório é a forma preferida para carregar entidades no Magento, pois eles dão uma camada a mais de abstração na forma como os dados são armazenados – no entanto não precisamos saber disso, só queremos carregar os dados.

Repositórios também são parte da API do Magento. Isso (felizmente) quer dizer que o Magento manterá compatibilidade reversa em futuras classes e métodos, e nosso código continuará funcionando em versões mais novas.

Como exemplo, nós vamos construir um novo Block que carregará os 5 produtos mais pesados do nosso catálogo.

Configurando a classe

Antes de começar, nós precisamos configurar o namespace, adicionar alguns use, e garantir que a classe do nosso bloco estende a classe core Template. Também adicionei um esboço de um método (stub) que vamos usar para carregar nossa lista de produtos.

Este artigo parte do princípio que você já criou a estrutura de um módulo para Magento 2.

namespace Magenteiro\HeavyProducts\Block;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Api\SortOrder;
use Magento\Framework\Api\SortOrderBuilder;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;

class ListProduct extends Template
{

    /**
     * @return ProductInterface[]
     */
    public function getProducts()
    {}

}

Injetando as dependências

Se você é aluno do curso de Magento 2, já deve estar dominando o assunto de injeção de dependências. Caso não seja, tem uma aula grátis sobre o assunto lá no site do curso onde eu desmistifico esse assunto.

O Magento 2 trouxe um ótimo sistema de injeção de dependências. Dependency injection é uma forma sofisticada de dizer “minha classe precisa acessar essas outras classes, você pode dar elas pra mim?“.

Nota: Via de regra nós nunca devemos usar a classe ObjectManager diretamente para instanciar outras classes. Sempre use injeção de dependência através do método __construct da sua classe.

Nós precisamos injetar o repositório de Produto, assim como algumas outras classes construtoras que vamos falar adiante. Repositórios estão geralmente localizados na pasta /Api dos módulos.

Podemos encontrar o repositório de Produto em <Magento_Catalog>/Api/ProductRepositoryInterface.php. Aqui podemos ver quais métodos estão disponíveis e que podemos usar na interface, incluindo o que vamos usar, getList.

Passando a classe para o nosso método __construct, o Magento irá instanciar ele pra gente e disponibilizá-lo internamente para nossa classe. Feito isso, tudo que precisamos fazer é associar estes objetos a propriedades privadas na nossa própria classe.

Nota: Como nossa classe está estendendo outra classe (Template), nós precisamos injetar a classe pai e todas as suas dependências, e chamar o construtor pai a partir do nosso próprio construtor.

private $productRepository;
private $searchCriteriaBuilder;
private $sortOrderBuilder;

public function __construct(
    ProductRepositoryInterface $productRepository,
    SearchCriteriaBuilder $searchCriteriaBuilder,
    SortOrderBuilder $sortOrderBuilder,
    Context $context,
    array $data = []
) {
    parent::__construct($context, $data);

    $this->productRepository = $productRepository;
    $this->searchCriteriaBuilder = $searchCriteriaBuilder;
    $this->sortOrderBuilder = $sortOrderBuilder;
}

Criando o SearchCriteria

Se olharmos o método getList, percebemos que ele requer um parâmetro: SearchCriteriaInterface. É por isso que precisamos injetar a classe construtora (SearchCriteriaBuilder) para criar este objeto pra gente.

Uma classe do tipo Builder é parecida com uma classe do tipo Factory, pois ela ajuda a instanciar uma outra classe pra gente. A diferença sutil é que queremos passar um monte de variáveis e parâmetros primeiro, então quando tivermos o novo objeto, ele já vai estar pronto pra gente usar.

Filtrando

O método addFilter no SearchCriteriaBuilder é usado para filtrar os produtos que queremos. No nosso caso, queremos filtrar baseado no campo peso (weight), usando um valor maior ou igual a 10kg (ou lbs caso seu Magento esteja configurado assim).

No método getProducts vamos adicionar o filtro:

$this->searchCriteriaBuilder->addFilter('weight', 10.0, 'gteq');

Ordenação no SearchCriteriaBuilder

Para ordenar nossa coleção, usaremos o método addSortOrder no SearchCriteriaBuilder, passando um objeto do tipo SortOrder. Para isso precisaremos de outro builder.

Vamos ordenar os produtos do mais pesado para o mais leve:

$sortOrder = $this->sortOrderBuilder
    ->setField('weight')
    ->setDirection(SortOrder::SORT_DESC)
    ->create();
    
$this->searchCriteriaBuilder->addSortOrder($sortOrder);

Limitando o Resultado

Se quisermos limitar o tamanho da coleção de produtos que estamos carregando, podemos usar o método setPageSize e setCurrentPage. Isto também é útil para fazer paginação.

Vamos limitar apenas os 5 produtos mais pesados:

$this->searchCriteriaBuilder
    ->setPageSize(5)
    ->setCurrentPage(1);

Criando o objeto

Agora tudo que precisamos fazer é criar (create) o objeto SearchCriteria:

$searchCriteria = $this->searchCriteriaBuilder->create();

Agora nós temos um objeto do tipo SearchCriteria completo para usar.

Usando o Repository

Por fim, nós podemos usar o repositório que criamos. O método getList retorna um objeto ProductSearchResultsInterface, que é útil para pegar metadados do nosso resultado, como o SearchCriteria usado, ou o total de registros encontrados.

Nós vamos usar o método getItems, que retorna um array de produtos.

$products = $this->productRepository
    ->getList($searchCriteria)
    ->getItems();

Juntando tudo

Abaixo você encontra a classe completa. Espero que ela mostre o quão fácil é utilizar os repositórios do Magento 2. Por favor, deixe seu comentário abaixo caso encontre qualquer inconsistência no artigo ou se houver algo que poderia ter sido mais claro. (Ou aproveite para discutir e se aprofundar mais no assunto, no grupo secreto de alunos do curso de Magento 2)

Divirta-se e carregue alguns produtos!

<?php

namespace Magenteiro\HeavyProducts\Block;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Api\SortOrder;
use Magento\Framework\Api\SortOrderBuilder;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;

class ListProduct extends Template
{

    /**
     * Product repository
     * @var ProductRepositoryInterface
     */
    private $productRepository;

    /**
     * SearchCriteria builder
     * @var SearchCriteriaBuilder
     */
    private $searchCriteriaBuilder;

    /**
     * SortOrder builder
     * @var SortOrderBuilder
     */
    private $sortOrderBuilder;

    /**
     * ListProduct constructor
     *
     * @param ProductRepositoryInterface $productRepository
     * @param SearchCriteriaBuilder $searchCriteriaBuilder
     * @param SortOrderBuilder $sortOrderBuilder
     * @param Context $context
     * @param array $data
     */
    public function __construct(
        ProductRepositoryInterface $productRepository,
        SearchCriteriaBuilder $searchCriteriaBuilder,
        SortOrderBuilder $sortOrderBuilder,
        Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
        $this->productRepository = $productRepository;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
        $this->sortOrderBuilder = $sortOrderBuilder;
    }

    /**
     * Get list of the 5 heaviest products
     *
     * @return ProductInterface[]
     */
    public function getProducts()
    {
        // Filter products weighing 10kg or more
        $this->searchCriteriaBuilder
            ->addFilter('weight', 10.0, 'gteq');

        // Sort products heaviest to lightest
        $sortOrder = $this->sortOrderBuilder
            ->setField('weight')
            ->setDirection(SortOrder::SORT_DESC)
            ->create();
        $this->searchCriteriaBuilder->addSortOrder($sortOrder);

        // Get the first 5 products
        $this->searchCriteriaBuilder
            ->setPageSize(5)
            ->setCurrentPage(1);

        // Create the SearchCriteria
        $searchCriteria = $this->searchCriteriaBuilder->create();

        // Load the products
        $products = $this->productRepository
            ->getList($searchCriteria)
            ->getItems();

        return $products;
    }

}

Este artigo foi escrito originalmente por Danny Nimmo e traduzido por mim (Ricardo Martins) com algumas modificações e com prévia autorização do autor. Confira o artigo original (em Inglês) aqui.
Últimos posts por Ricardo Martins (exibir todos)
Comentários

Deixe seu comentário

[fbcomments url="https://www.magenteiro.com/blog/magento-2/como-usar-o-repository-pattern-no-magento-2/"]