O histórico de coleções está no Magento 2?

25

Eu sei que muito código atualmente no Magento 2 (2.1.2) é mais ou menos portado do Magento 1 e que muito código será substituído por um equivalente no futuro. Nesse aspecto, estou me perguntando qual é o futuro das coleções no Magento 2.

Deixe-me explicar:

Magento 1:

No Magento 1, estamos acostumados a obter uma coleção como esta:

$products = Mage::getModel('catalog/product')->getCollection();

Poderíamos então aplicar filtros e outras operações à coleção:

$products->addAttributeToFilter('price', ['gteq' => 10]);
$products->addFieldToFilter('created_at', ['lt' => '2016-10-10']);
$products->setPageSize(10);
// ... etc ...

E por último mas não menos importante, nossa coleção retornaria os modelos:

foreach ($products as $product) {
    echo get_class($product); // Mage_Catalog_Model_Product
}

Magento 2:

O Magento adiciona muitas novas camadas de abstração, implementando uma maneira mais sólida de trabalhar. Isso significa que, quando queremos uma lista de entidades, solicitamos em um repositório:

$productResults = $this->productRepository->getList($searchCriteria);

Se queremos aplicar filtros, usamos uma combinação de SearchCriteriaBuilder, the FilterGroupBuilder, the FilterBuildere the SortOrderBuilder:

$this->searchCriteriaBuilder->addSortOrder(
    $this->sortOrderBuilder
        ->setField('created_at')
        ->setAscendingDirection()
        ->create()
);
$priceFilter = $this->filterBuilder
    ->setField('price')
    ->setValue(10)
    ->setConditionType('gteq')
    ->create();
$createdAtFilter = $this->filterBuilder
    ->setField('created_at')
    ->setValue('2016-10-10')
    ->setConditionType('lt')
    ->create();
$filterGroups = [
    $this->filterGroupBuilder->addFilter($priceFilter)->create(),
    $this->filterGroupBuilder->addFilter($createdAtFilter)->create()
];

E se queremos iterar sobre nossos resultados, obtemos modelos de dados, não modelos reais (herdados):

foreach ($productResults->getItems() as $product) {
    echo get_class($product); // \Magento\Catalog\Model\Data\Product
}

Esse tipo de abstração segue o princípio do SOLID e abrange o princípio da 'composição sobre herança' . Quaisquer operações 'exóticas' que de outra forma seriam realizadas na coleção (como junções para exemplos) são realizadas internamente no repositório, o que também facilita o uso fora do módulo.

A questão:

Tudo isso me faz pensar: com toda a abordagem de repositório / modelo de dados, existe algum espaço no futuro do Magento 2 para coleções? As coleções devem ser usadas apenas internamente pelo próprio módulo e não fora dele? Ou será preterido em favor do Entity Manager?

Atualmente, se você deseja adotar os Modelos de Dados, ainda precisa criar um modelo herdado (herdado de \Magento\Framework\Model\AbstractModel) apenas para que a coleção funcione (já que Magento\Framework\Data\Collection::setItemObjectClassrequer que o modelo seja estendido Magento\Framework\DataObject). E você precisa fazer a coleta para poder filtrar em seu repositório. Mas, novamente, no repositório você precisa 'converter' seu Modelo (regular) em um Modelo de Dados.

Ou temos que implementá-lo como o Repositório de Pedidos, em que getList()retorna uma instância de Magento\Sales\Api\Data\OrderSearchResultInterface, mas debaixo d'água os resultados da pesquisa nada mais são do que uma coleção regular que implementa essa interface. Curiosidade: os resultados da pesquisa indicam que ele retornará uma matriz de Modelos de Dados ( Magento\Sales\Api\Data\OrderInterface[]), mas se você analisar o código, getItems()executará o Magento\Framework\Data\Collection::getItems()que, em troca, não retornará os modelos de dados, mas os modelos de ordem (conforme definido por Magento\Sales\Model\ResourceModel\Order\Collection::_construct()). Tanta coisa para 'composição sobre herança'.

Muitas perguntas sobre qual é o caminho correto no Magento 2. Novamente, existem 100 maneiras de fazer a mesma coisa, mas o que é 'The Magento Way'? Ou estou totalmente no caminho errado aqui?

Giel Berkers
fonte
2
Fazendo as perguntas reais aqui +1. Eu realmente adoraria uma resposta central do desenvolvedor aqui
Marius
Acredito que o plano é que as coleções sejam descontinuadas. No entanto, como você notou, isso não está nem perto de ser realizado e há muitas áreas que parecem estar em vários estados de refatoração (com a API estável como Magento \ Sales \ Api \ Data \ OrderSearchResultInterface, permite que o Magento substitua o que mais tarde, sob o capô). Não ajuda que as várias implementações do getList ainda não sejam tão capazes quanto o que podemos fazer atualmente com coleções. A inconsistência que você notou em relação ao retorno declarado pode ser útil para um problema no github.
Kristof em Fooman

Respostas:

16

As coleções não estão obsoletas agora. Enquanto alguns módulos já expõem APIs de contrato de serviço, outros ainda expõem apenas APIs de modelo / coleção.

O plano é:

  1. Reflita o estado atual com melhor cobertura do @api: anote coleções abstratas e coleções específicas em alguns módulos com o @api
  2. Melhore a estrutura de persistência para permitir a fácil criação de Contratos de Serviço sem depender de APIs baseadas em herança: Coleções, Modelos, Modelos de Recursos
  3. Descontinuar a coleção abstrata para não promover implementações baseadas em coleções de contratos de serviço
  4. Liberar gradualmente versões mais recentes de módulos com APIs de contrato de serviço

Portanto, as coleções serão descontinuadas em algum momento, mas agora elas são uma das APIs do Magento 2.

Quanto à implementação de Contratos de Serviço, - Modelos e Coleções são a única maneira conveniente de implementá-los no Magento <= 2.1. Contratos de serviço são apenas interfaces. Sua implementação não faz parte da API pública e pode ser alterada posteriormente.

Anton Kril
fonte
11
Obrigado pela sua resposta. Então, qual é o seu conselho para desenvolvedores que criam novos módulos? Minha estratégia atual é criar contratos de serviço que (debaixo d'água) ainda usem coleções porque: a) facilita a filtragem eb) o gerente da entidade ainda é muito experimental / não documentado. Em algum momento, o funcionamento interno pode ser substituído por qualquer outra coisa, mas a interface permanece a mesma. Mas se eu entendi sua resposta corretamente, esse é o caminho certo por enquanto, certo?
Giel Berkers
Corrigir. Eu editei minha resposta para refletir isso.
Anton Kril
11
Considerando o exposto, qual seria a maneira correta de implementar a funcionalidade que requer dados que não podem ser buscados por meio de contratos de serviço? Por exemplo, se o módulo A exigir que todos os pedidos sejam filtrados pela forma de pagamento.
Stjepan