¿Las colecciones son historia en Magento 2?

25

Sé que una gran cantidad de código que se encuentra actualmente en Magento 2 (2.1.2) está más o menos portado desde Magento 1 y que una gran cantidad de código será sustituido por un equivalente en el futuro. En este aspecto, me pregunto cuál es el futuro de las colecciones en Magento 2.

Dejame explicar:

Magento 1:

En Magento 1 estamos acostumbrados a obtener una colección como esta:

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

Luego podríamos aplicar filtros y otras operaciones a la colección:

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

Y por último pero no menos importante, nuestra colección devolvería los modelos:

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

Magento 2:

Magento agrega muchas capas nuevas de abstracción, implementando una forma de trabajo más SÓLIDA. Esto significa que cuando queremos una lista de entidades, la pedimos desde un repositorio:

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

Si queremos aplicar filtros, usamos una combinación de los SearchCriteriaBuilder, los FilterGroupBuilder, los FilterBuildery los 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()
];

Y si queremos iterar sobre nuestros resultados, obtenemos modelos de datos, no modelos reales (heredados):

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

Este tipo de abstracción sigue el principio SÓLIDO y abarca el principio de "composición sobre herencia" . Cualquier operación 'exótica' que de otro modo se realizaría en la colección (como las combinaciones para ejemplos) se realiza internamente en el repositorio, lo que hace que sea más fácil de usar fuera del módulo.

La pregunta:

Todo esto me hace preguntarme: con todo el enfoque de repositorio / modelo de datos, ¿hay espacio en el futuro de Magento 2 para las colecciones? ¿Las colecciones solo deben ser utilizadas internamente por el módulo en sí y no fuera de él? ¿O van a quedar en desuso en favor del Entity Manager?

Actualmente, si desea adoptar los Modelos de datos, aún tiene que crear un modelo heredado (heredado de \Magento\Framework\Model\AbstractModel) solo para que la colección funcione (ya que Magento\Framework\Data\Collection::setItemObjectClassrequiere que el modelo se extienda desde Magento\Framework\DataObject). Y necesita una colección para poder filtrar en su repositorio. Pero, de nuevo, en el repositorio debe 'convertir' su Modelo (regular) en un Modelo de Datos.

¿O tenemos que implementarlo como el Repositorio de pedidos, donde getList()devuelve una instancia de Magento\Sales\Api\Data\OrderSearchResultInterface, pero bajo el agua los resultados de búsqueda no son más que una colección regular que implementa esta interfaz. Dato curioso: los resultados de búsqueda indican que devolverá una matriz de modelos de datos ( Magento\Sales\Api\Data\OrderInterface[]), pero si analiza el código, getItems()ejecutará lo Magento\Framework\Data\Collection::getItems()que a cambio no devuelve los modelos de datos, sino los modelos de orden (según lo establecido por Magento\Sales\Model\ResourceModel\Order\Collection::_construct()). Esto en cuanto a 'composición sobre herencia'.

Muchas preguntas sobre cuál es la forma correcta en Magento 2. Una vez más, hay 100 formas de hacer lo mismo, pero ¿qué es 'The Magento Way'? ¿O simplemente estoy totalmente en el camino equivocado aquí?

Giel Berkers
fuente
2
Hacer las preguntas reales aquí +1. Realmente me encantaría una respuesta de desarrollo principal aquí
Marius
Creo que el plan es que las Colecciones se eliminen paulatinamente. Sin embargo, como notó, esto no está ni siquiera cerca de lograrse y hay muchas áreas que parecen estar en varios estados de refactorización (tener la API estable como Magento \ Sales \ Api \ Data \ OrderSearchResultInterface, permite a Magento reemplazar lo que sucede debajo del capó más fácilmente más adelante). No ayuda que las diversas implementaciones de getList aún no sean tan capaces como lo que podemos hacer actualmente con las colecciones. La inconsistencia que notó alrededor del retorno declarado podría ser digna de un problema en github.
Kristof en Fooman

Respuestas:

16

Las colecciones no están en desuso ahora. Si bien algunos módulos ya exponen las API de contrato de servicio, otros aún exponen solo las API de modelo / colección.

El plan es:

  1. Refleje el estado actual con una mejor cobertura @api: anote colecciones abstractas y colecciones específicas en algunos módulos con @api
  2. Mejore el marco de persistencia para permitir la creación fácil de contratos de servicio sin depender de API basadas en herencia: colecciones, modelos, modelos de recursos
  3. Desaprobar la recopilación de resumen para no promover implementaciones basadas en la recopilación de contratos de servicio
  4. Gradualmente, publique versiones más nuevas de módulos con API de contrato de servicio

Por lo tanto, las colecciones quedarán obsoletas en algún momento, pero ahora son una de las API de Magento 2.

En cuanto a la implementación de los contratos de servicio, los modelos y colecciones son la única forma conveniente de implementarlos en Magento <= 2.1. Los contratos de servicio son solo interfaces. Su implementación no es parte de una API pública y puede modificarse más adelante.

Anton Kril
fuente
1
Gracias por tu respuesta. Entonces, ¿cuál es su consejo para los desarrolladores que crean nuevos módulos? Mi estrategia actual es crear contratos de servicio que (bajo el agua) sigan utilizando colecciones porque a) facilita el filtrado, yb) el administrador de la entidad todavía es demasiado experimental / indocumentado. En algún momento, el funcionamiento interno puede ser reemplazado por cualquier otra cosa, pero la interfaz sigue siendo la misma. Pero si entiendo tu respuesta correctamente, esa es la forma correcta por ahora, ¿verdad?
Giel Berkers
Correcto. Edité mi respuesta para reflejar esto.
Anton Kril
1
Teniendo en cuenta lo anterior, ¿cuál sería la forma correcta de implementar la funcionalidad que requiere datos que no se pueden obtener a través de contratos de servicio? Por ejemplo, si el módulo A requiere que todas las órdenes se filtren por método de pago.
Stjepan