23

What would be the latest best practice to load Order using increment ID (instead of Order ID) using OrderRepository

frostshoxx
  • 625
  • 2
  • 8
  • 24

2 Answers2

35

Magento 2 uses Service Contracts for retrieving and saving objects. In Magento this layer is formed by Repositories, which are managers with get() and save() methods. This keeps user code away from Model calls. Don't call model methods (like load() or save() or loadByIncrementId()) directly, they are being deprecated as custom code should use the Service Contracts. Also, don't use the API from within Magento like Khoa is suggesting, it does not make sense. The API is for connecting Magento with other systems.

Inject OrderRepository and SearchCriteriaBuilder in your 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; parent::__construct($context); }

And in your function:

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

// $orderList is now an array of Orders with this incrementId, which is just one order obviously

/** @var \Magento\Sales\Model\Order $order */ $order = reset($orderList); // Your logic here $order = $this->orderRepository->save($order);

Official Magento PHP Developer guide on magento.com

Code by Mulderea on github

Ricardo Martins
  • 1,935
  • 16
  • 39
Jacques
  • 1,026
  • 10
  • 21
  • I am getting error like : Cannot use object of type Magento\Sales\Model\ResourceModel\Order\Collection as array at $order = $orderList[0]; – Ashish Raj Feb 13 '17 at 14:26
  • That's odd, I got an array. Which version are you on? But with a collection you can just replace $order = $orderList[0] with $order = $orderList->getFirstItem() to get the first (and only) item from the collection. – Jacques Feb 14 '17 at 08:42
  • I am in version 2.1.3. and I need to load order object for load payment object .. I have done $order = $orderList->getFirstItem(); $payment = $order->getPayment(); But getting nothing in $payment

    Please check my problem here http://magento.stackexchange.com/questions/158935/magento-2-unable-to-set-payment-transaction-id-after-successful-payment-process

    – Ashish Raj Feb 14 '17 at 09:20
  • 1
    I had a bug with the accepted answer. This solved it. Thanks for the good solution – CompactCode Aug 31 '18 at 02:44
  • In Magento 2.3.x I need to get the order this way: $order = $orderList['000000001']; – phse Sep 19 '19 at 16:06
  • 1
    @ph.dev $order = end($orderList) would be better since '000000001' here is order ID which you probably don't know. – Krzysztof Wołowski Nov 18 '19 at 11:59
  • @KrzysztofWołowski Upvote and you are right. $order = reset($orderList) could be used too, and maybe more semantic. – Key Shang Sep 17 '20 at 09:54
22

As far as I know, we should use \Magento\Sales\Api\Data\OrderInterface.

/** @var \Magento\Sales\Api\Data\OrderInterfaceFactory $order **/

protected $orderFactory;

public function __construct(
    \Magento\Sales\Api\Data\OrderInterfaceFactory $orderFactory,
    ......
) {
    $this->orderFactory = $orderFactory;

}

Load order object by increment id:

$this->orderFactory->create()->loadByIncrementId('00001952-42');

[EDIT] should try with service contracts. Try Jacco's answer.

Khoa TruongDinh
  • 32,054
  • 11
  • 88
  • 155
  • 3
    Please don't use underscores in your variable names. PHP has had access modifiers since PHP 5, which is now 12 years old. You should use modern programming practices, especially in answers here. – Jacques Jan 18 '17 at 11:18
  • @JaccoAmersfoort Thanks your input. However, I also took a look your answer below. I need to check and confirm. – Khoa TruongDinh Jan 18 '17 at 12:46
  • this is not working in my controller... please suggest why? – Ashish Raj Feb 14 '17 at 09:25
  • @AshishRaj you can show me your controller? You should open new question. I will take a look. – Khoa TruongDinh Feb 14 '17 at 09:27
  • yes but its little big in lines... so will not come inside the comment box... but i m doing the same thing .. loading as above in constructor and using as like $order = $this->order->loadByIncrementId('00001952-42'); and then doing $payment = $order->getPayment(); But getting nothing in $payment Please check my problem here http://magento.stackexchange.com/questions/158935/magento-2-unable-to-set-payment-transaction-id-after-successful-payment-process – Ashish Raj Feb 14 '17 at 09:32
  • @AshishRaj Okay! I'm checking your question. – Khoa TruongDinh Feb 14 '17 at 09:33
  • 1
    This method should not be used even if it "works". One: the di injection is a shared object unless it is specified to not be; anytime you insert OrderInterface in you'll be using the exact same object. If you really want to go this route use OrderInterfaceFactory and then call create(). Second, you should be using the service contracts as in Jacco's answer. – Ian Jul 18 '17 at 22:03
  • @Ian I agreed with you that we should use service contracts. I also voted up Jacco's answer. – Khoa TruongDinh Jul 19 '17 at 01:15
  • 2
    version 2.2.2, use \Magento\Sales\Api\OrderRepositoryInterface and its get() method – LucScu Mar 06 '18 at 14:41
  • 2
    service contracts must be taken in consideration. – Thiago Lima Jul 02 '18 at 10:25
  • 1
    @ThiagoLima yes, I agreed with you! I also voted the service contracts answer. – Khoa TruongDinh Jul 03 '18 at 01:15