История коллекций в Magento 2?

25

Я знаю, что большая часть кода, который в настоящее время находится в Magento 2 (2.1.2), более или менее перенесена из Magento 1, и что большая часть кода будет заменена эквивалентом в будущем. В этом аспекте мне интересно, каково будущее коллекций в Magento 2.

Позволь мне объяснить:

Magento 1:

В Magento 1 мы привыкли получать такую ​​коллекцию:

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

Затем мы можем применить фильтры и другие операции к коллекции:

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

И, наконец, наша коллекция вернет модели:

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

Magento 2:

Magento добавляет много новых слоев абстракции, реализуя более твердый способ работы. Это означает, что когда мы хотим получить список объектов, мы запрашиваем его из репозитория:

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

Если мы хотим применить фильтры мы используем комбинацию из SearchCriteriaBuilder, то FilterGroupBuilder, то FilterBuilderи 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()
];

И если мы хотим перебрать наши результаты, мы получим модели данных, а не фактические (унаследованные) модели:

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

Этот вид абстракции следует принципу SOLID и охватывает принцип «композиция поверх наследования» . Любые «экзотические» операции, которые в противном случае были бы выполнены в коллекции (например, объединения для примеров), выполняются внутри хранилища, что также облегчает использование вне модуля.

Вопрос:

Все это заставляет меня задуматься: при всем подходе к репозиторию / модели данных, есть ли место в будущем Magento 2 для коллекций? Разве коллекции используются только самим модулем, а не за его пределами? Или не рекомендуется использовать Entity Manager?

В настоящее время, если вы хотите использовать модели данных, вам все равно нужно создать унаследованную модель (унаследованную от \Magento\Framework\Model\AbstractModel) только для того, чтобы заставить коллекцию работать (поскольку Magento\Framework\Data\Collection::setItemObjectClassтребуется, чтобы модель расширялась от Magento\Framework\DataObject). И вам нужно собрать, чтобы иметь возможность фильтровать в вашем хранилище. Но опять же, в хранилище вы должны «преобразовать» свою (обычную) модель в модель данных.

Или мы должны реализовать его как репозиторий заказов, где getList()возвращается экземпляр Magento\Sales\Api\Data\OrderSearchResultInterface, но под водой результаты поиска - не что иное, как обычная коллекция, реализующая этот интерфейс. Интересный факт: в результатах поиска указывается, что он вернет массив Data Models ( Magento\Sales\Api\Data\OrderInterface[]), но, если вы проанализируете код, getItems()он выполнит, Magento\Framework\Data\Collection::getItems()который, в свою очередь, вернет не модели данных, а модели порядка (как установлено Magento\Sales\Model\ResourceModel\Order\Collection::_construct()). Вот вам и «композиция, а не наследство».

Много вопросов о том, как правильно поступить в Magento 2. Опять же, есть 100 способов сделать то же самое, но что такое «Путь Magento»? Или я просто на неправильном пути?

Гиль Беркерс
источник
2
Задавать реальные вопросы здесь +1. Мне бы очень хотелось получить ответ от главного разработчика
Marius
Я считаю, что план по поэтапному отказу от Коллекций. Однако, как вы заметили, это даже близко не близко к завершению, и есть много областей, которые, по-видимому, находятся в различных состояниях рефакторинга (имея стабильный API как Magento \ Sales \ Api \ Data \ OrderSearchResultInterface, позволяет Magento заменить то, что бывает под капотом легче потом). Это не помогает, что различные реализации getList еще не настолько эффективны, как то, что мы можем сейчас делать с коллекциями. Несоответствие, которое вы отметили в отношении заявленного возврата, может оказаться достойным решения проблемы на github.
Кристоф в Фуман

Ответы:

16

Коллекции не устарели сейчас. Хотя некоторые модули уже предоставляют API-интерфейсы контрактов на обслуживание, другие по-прежнему предоставляют только API-интерфейсы Model / Collection.

План такой:

  1. Отражайте текущее состояние с лучшим охватом @api: аннотируйте абстрактные коллекции и определенные коллекции в некоторых модулях с помощью @api
  2. Улучшите структуру постоянства, чтобы упростить создание контрактов на обслуживание без использования API на основе наследования: коллекции, модели, модели ресурсов
  3. Устаревать реферативную коллекцию, чтобы не продвигать основанные на коллекциях реализации контрактов на обслуживание
  4. Постепенно выпускать новые версии модулей с API сервисного контракта

Поэтому коллекции в какой-то момент будут устаревшими, но теперь они являются одним из API Magento 2.

Что касается реализации сервисных контрактов, - модели и коллекции являются единственным удобным способом их реализации в Magento <= 2.1. Сервисные контракты - это просто интерфейсы. Их реализация не является частью публичного API и может быть изменена позже.

Антон Криль
источник
1
Спасибо за Ваш ответ. Так что вы посоветуете разработчикам, которые создают новые модули? Моя текущая стратегия состоит в том, чтобы создавать сервисные контракты, которые (под водой) все еще используют коллекции, потому что a) это облегчает фильтрацию, и b) менеджер сущностей все еще слишком экспериментален / недокументирован. В какой-то момент внутреннюю работу можно заменить чем-нибудь еще, но интерфейс остается прежним. Но если я правильно понимаю ваш ответ, то это правильный путь, верно?
Гиль Беркерс
Правильный. Я отредактировал свой ответ, чтобы отразить это.
Антон Криль
1
Учитывая вышесказанное, что было бы правильным способом реализовать функциональность, которая требует данных, которые не могут быть получены через сервисные контракты? Например, если для модуля A требуются все заказы, отфильтрованные по способу оплаты.
Степан