Question

MAGENTO v2.2.6

To better illustrate my question here's an example. When using the ordinary collection I can limit the attributes/fields returned like so:

NOTE: I wouldn't normally use the object manager directly, this is just an example from an ad-hoc script I created.

$productCollection = $objectManager->get(Magento\Catalog\Model\ResourceModel\Product\Collection::class);
$productCollection
    ->addAttributeToSelect('sku') /*<-- THIS IS THE FUNCTIONALITY I WANT TO MIMIC*/
    ->addFieldToFilter('manufacturer', ['eq' => 3])
    ->addFieldToFilter('price',['eq' => 234]);

foreach ($productCollection as $product){
    print_r($product->getData());
}

The above will return the following values from my particular store:

Array
(
    [entity_id] => 185
    [attribute_set_id] => 15
    [type_id] => simple
    [sku] => SKY-5001
    [has_options] => 0
    [required_options] => 0
    [created_at] => 2012-11-08 23:52:51
    [updated_at] => 2018-11-13 12:38:30
    [manufacturer] => 3
    [price] => 234.0000
)
Array
(
    [entity_id] => 186
    [attribute_set_id] => 15
    [type_id] => simple
    [sku] => SKY-5010
    [has_options] => 0
    [required_options] => 0
    [created_at] => 2012-08-11 23:52:54
    [updated_at] => 2018-11-13 12:38:30
    [manufacturer] => 3
    [price] => 234.0000
)
...

When using the getList() function located within \Magento\Catalog\Model\ProductRepository.php like in the code block below, all values from the entity are returned. I'd like to minimize the amount of data returned to only what is needed.

$searchCriteriaBuilder = $objectManager->create('Magento\Framework\Api\SearchCriteriaBuilder');
$productRepository = $objectManager->get(Magento\Catalog\Api\ProductRepositoryInterface::class);
$productSearch = $searchCriteriaBuilder->addFilter('manufacturer', 3, 'eq')->addFilter('price', 234, 'eq')->create();
$products = $productRepository->getList($productSearch)->getItems();

foreach ($products as $product){
    print_r($product->getData());
}

Here's is what's returned using the ProductRepository:

Array
(
    [entity_id] => 185
    [attribute_set_id] => 15
    [type_id] => simple
    [sku] => SKY-5001
    [has_options] => 0
    [required_options] => 0
    [created_at] => 2012-11-08 23:52:51
    [updated_at] => 2018-11-13 12:38:30
    [status] => 1
    [visibility] => 4
    [manufacturer] => 3
    [price] => 234.0000
    [description] => The 5001 On/Off Fireplace Remote Control with Backlit Touch Screen
    ...
    [size_name] => 
    [parent_sku] => 
    [color_name] => 
    [shape_name] => 
    [material_name] => 
    [inchoo_meta_robots] => 
    [mpn] => SKY-5001
    [banner_filename] => 
    [banner_category_url] => 
    [shipping_standard] => Order by 1 PM CST for Same Day Shipping
    [google_name] => 
    [remote_function_filter] => 6450
    [major_category] => Fireplace Remotes
    [sub_category1] => On/Off
    [amasty_preorder_note] => 
    [amasty_preorder_cart_label] => 
    [is_recurring] => 0
    [tax_class_id] => 2
    [fuel_type] => 
...

I've looked through the code base to no avail. Is there a way to select only specific attributes when using the Repository's getList()? I know using service contracts are the best practice, and I want to make sure I follow best practices to make upgrades and such less of a headache in the future, but I don't want to have to return every attribute or field value when getting a collection.

Était-ce utile?

La solution

So after looking into this issue, it seems that there isn't currently (as of Magento v2.2.6) function that you can use to mimic the functionality of addAttributeToSelect. It looks like like most realistic option would be to create a custom function based on getList() and add in your own attributes that you'd like to select manually. Looking at the getList() function in vendor/magento/module-catalog/Model/ProductRepository.php

    public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria)
    {
        /** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $collection */
        $collection = $this->collectionFactory->create();
        $this->extensionAttributesJoinProcessor->process($collection);

        $collection->addAttributeToSelect('*'); /*YOU'D WANT TO SELECT THE SPECIFIC ATTRIBUTES HERE*/
        $collection->joinAttribute('status', 'catalog_product/status', 'entity_id', null, 'inner');
        $collection->joinAttribute('visibility', 'catalog_product/visibility', 'entity_id', null, 'inner');

        $this->collectionProcessor->process($searchCriteria, $collection);

        $collection->load();

        $collection->addCategoryIds();
        $searchResult = $this->searchResultsFactory->create();
        $searchResult->setSearchCriteria($searchCriteria);
        $searchResult->setItems($collection->getItems());
        $searchResult->setTotalCount($collection->getSize());

        foreach ($collection->getItems() as $product) {
            $this->cacheProduct(
                $this->getCacheKey(
                    [
                        false,
                        $product->hasData(\Magento\Catalog\Model\Product::STORE_ID) ? $product->getStoreId() : null
                    ]
                ),
                $product
            );
        }

        return $searchResult;
    }

So if you really want to use the Product Repository you could extend from this class and add in your own additional custom getList() function (DON'T OVERWRITE THE getList() FUNCTION ITSELF) like getListSku() in my case and update the line $collection->addAttributeToSelect('*') to $collection->addAttributeToSelect('sku').

Licencié sous: CC-BY-SA avec attribution
Non affilié à magento.stackexchange
scroll top