This is my first stack exchange question, so I apologise in advance if I've not asked it in the correct way. I've just begun the process of getting to grips with Magento 2 in preparation for a migrating a few sites from Magento 1.

I've been reading quite a few posts on the best way to load an order from an increment id and it appears that that the recommended way is using repositories and SearchCriteriaBuilder objects as per this post Magento 2.1.1 How to load Order with Increment ID using OrderRepository object. The post suggests passing the SearchCriteriaBuilder object into the constructor.

private $orderRepository;
private $searchCriteriaBuilder;

public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        \Magento\Sales\Model\OrderRepository $orderRepository,
        \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
    $this->orderRepository = $orderRepository;
    $this->searchCriteriaBuilder = $searchCriteriaBuilder;

and then obtaining the order using something like

$searchCriteria = $this->searchCriteriaBuilder
    ->addFilter('increment_id', '000000001', 'eq')->create();
$orderList = $this->orderRepository->getList($searchCriteria)->getItems();

$order = $orderList[0];

My question, however, is whether this would work in a loop

foreach ($incrementIds as $incrementId) {
    $searchCriteria = $this->searchCriteriaBuilder
        ->addFilter('increment_id', $incrementId, 'eq')->create();
    $orderList = $this->orderRepository->getList($searchCriteria)->getItems();
    $order = $orderList[0];

    ...Do some work on order...

It doesn't look like there is an obvious method to reset the searchCriteriaBuilder object on each iteration, so on the second iteration I believe the second filter would get applied as well as the first and no rows would be returned.

Is the way round this to instantiate a new SearchCriteriaBuilder instance using a SearchCriteriaBuilderFactory on each iteration of the loop?

Would I be better just instantiating \Magento\Sales\Model\Order objects and loading those instead using the built in loadByIncrementId method?

Regards Mark

1 Answer 1


Have you tried the loop? Might work.

Alternative is to rewrite your query so can pass array plus encapsulate in single method to promote reusability.

public function getProducts(array $productIds): array
        $this->searchCriteriaBuilder->addFilter('entity_id', $productIds, 'in');
        $searchCriteria = $this->searchCriteriaBuilder->create();
        $products = $this->productRepository->getList($searchCriteria)->getItems();
        return $products;

Interfaces and repositories should be preferred instead of factory methods simply because although more verbose the code should never change despite framework changes and updates underneath.

That said I learnt from magento 1 so my brain is hard wired to write factory methods.

If you directly instantiate entity models outside of factory pattern stuff will break.

  • Thanks for the reply. I tried the loop and it actually works fine. I imagine the create method on the SearchCriteriaBuilder object must return a SearchCriteria object whilst resetting the SearchCriteriaBuilder object so that it can be used again.
    – Mark H
    Sep 26, 2019 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.