I know that a lot of code that is currently in Magento 2 (2.1.2) is more or less ported from Magento 1 and that a lot of code will be substituted by an equivalent in the future. In this aspect, I'm wondering what's the future of collections in Magento 2.
Let me explain:
Magento 1:
In Magento 1 we are used to get a collection like this:
$products = Mage::getModel('catalog/product')->getCollection();
We could then apply filters and other operations to the collection:
$products->addAttributeToFilter('price', ['gteq' => 10]);
$products->addFieldToFilter('created_at', ['lt' => '2016-10-10']);
$products->setPageSize(10);
// ... etc ...
And last but not least, our collection would return the models:
foreach ($products as $product) {
echo get_class($product); // Mage_Catalog_Model_Product
}
Magento 2:
Magento adds a lot of new layers of abstraction, implementing a more SOLID way of working. This means that when we want a list of entities, we ask it from a repository:
$productResults = $this->productRepository->getList($searchCriteria);
If we want to apply filters we use a combination of the SearchCriteriaBuilder
, the FilterGroupBuilder
, the FilterBuilder
and 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()
];
And if we want to iterate over our results, we get Data Models, not actual (inherited) models:
foreach ($productResults->getItems() as $product) {
echo get_class($product); // \Magento\Catalog\Model\Data\Product
}
This kind of abstraction follows the SOLID principle and embraces the 'composition over inheritance'-principle. Any 'exotic' operations that would be otherwise done on the collection (like joins for examples) are done internaly in the repository, which makes it also easier to use outside of the module.
The question:
All of this makes me wonder: with the whole repository / data model-approach, is there any room in the future of Magento 2 for collections? Are collections only to be used internally by the module itself and not outside of it? Or are the going to be deprecated in favour of the Entity Manager?
Currently, if you want to embrace Data Models, you still have to create an inherited model (inherited from \Magento\Framework\Model\AbstractModel
) just to get the collection working (since Magento\Framework\Data\Collection::setItemObjectClass
requires the model to extend from Magento\Framework\DataObject
). And you need to collection to be able to filter in your repository. But then again, in the repository you have to 'convert' your (regular) Model to a Data Model.
Or do we have to implement it like the Order Repository, where the getList()
returns an instance of Magento\Sales\Api\Data\OrderSearchResultInterface
, but under water the search results are nothing more than a regular collection that implements this interface. Fun fact: the search results states it will return an array of Data Models (Magento\Sales\Api\Data\OrderInterface[]
), but if you analyze the code, getItems()
will execute Magento\Framework\Data\Collection::getItems()
which in return returns not the data models, but the order models (as set by Magento\Sales\Model\ResourceModel\Order\Collection::_construct()
). So much for 'composition over inheritance'.
A lot of questions on what's the proper way in Magento 2. Again, there are 100 ways of doing the same thing, but what is 'The Magento Way'? Or am I just totally on the wrong track here?