5 min readUpdated May 18, 2025

How to Retrieve 'Paid' Orders in Shopware 6

A step-by-step guide to fetching orders by payment state in Shopware 6, utilizing the powerful Criteria API.

Written by

PHPShopwareBackend Development

Fetching 'Paid' Orders in Shopware 6: A Developer's Guide

As a software developer working with Shopware 6, one often encounters the need to retrieve orders based on their payment state—be it for generating reports, synchronizing with external systems, or just for administrative purposes. Today, I will walk you through a reliable method to get orders by a specific state, such as 'paid', using Shopware's robust Criteria API.

Understanding the Criteria API

Shopware 6 provides a flexible and efficient way to query data using its Criteria API. It is built to accommodate complex search requirements, enabling developers to construct detailed and specific queries. Leveraging this API allows us to filter orders by various conditions, such as payment state, order date, and more.

Setting Up the PHP Class

We'll create a class named MyLovelyClass within our plugin's service namespace. This class is responsible for interfacing with the EntityRepositoryInterface to fetch the data. We're injecting both EntityRepositoryInterface and LoggerInterface into our class via the constructor. This sets us up with access to the order repository and logging capabilities for debugging purposes.

1<?php 2 3namespace Plugin\Service\ScheduledTask; 4 5use DateTime; 6use Psr\Log\LoggerInterface; 7use Shopware\Core\Framework\Context; 8use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface; 9use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; 10use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; 11use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter; 12use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter; 13 14class MyLovelyClass 15{ 16 private EntityRepositoryInterface $orderRepository; 17 private LoggerInterface $logger; 18 19 // Constructor and other methods... 20}

Crafting the Query to Fetch Paid Orders

Within the MyLovelyClass, I define a method called getAndExecutePaidOrders which accepts the current Context as a parameter. The process begins by creating a DateTime object to set our desired time range - in this case, the past six weeks.

Next, I establish a Criteria object which allows me to specify the details of the query. I add an association to the orderCustomer to gain access to related customer data if needed.

The core of our query lies within the addFilter method, which uses a MultiFilter to combine multiple conditions using a logical AND. The first condition is a RangeFilter on the orderDate to ensure we're only looking at recent orders. The second, and crucial one, is an EqualsFilter that specifies the technicalName of the payment state to be 'paid'.

1// Method within MyLovelyClass 2 3public function getAndExecutePaidOrders(Context $context): void 4{ 5 // Random date for recent orders 6 $startDay = new DateTime(); 7 $startDay->modify('-3 weeks'); 8 9 $criteria->addFilter( 10 new MultiFilter( 11 MultiFilter::CONNECTION_AND, 12 [ 13 /** 14 * A random other filter 15 */ 16 new RangeFilter( 17 'orderDate', 18 [RangeFilter::GTE => $startDay->format('Y-m-d H:i:s')] 19 ), 20 21 /** 22 * The filter for the state of the payment 23 */ 24 new EqualsFilter( 25 'transactions.stateMachineState.technicalName', 26 'paid' // <-- state 27 ) 28 ] 29 ) 30 ); 31 32 // Simpler alternative: using the state filter without other filters: 33 // $criteria->addFilter(new EqualsFilter('transactions.stateMachineState.technicalName', 'paid')) 34 35 36}

Paginating Through Results

Since performance is key, especially with large datasets, I apply pagination to our query using setLimit. I've initially set the batch size to 50, but this can be adjusted based on specific needs. With pagination in place, I utilize a do-while loop to iterate through all the pages of results, calling a custom method doSomethingWithSingleOrder for each order that's been fetched. The loop continues until no more orders are left to process.

1// Pagination setup and loop within the method 2 3$criteria->setLimit(50); // Adjust batch size as needed 4 5$offset = 0; 6do { 7 // Fetching orders and processing them 8} while ($orders->count() > 0);

Conclusion

This walkthrough demonstrates how I leverage Shopware 6's Criteria API to retrieve orders based on their payment state. By applying precise filters and thoughtful pagination, I efficiently handle potentially large datasets while minimizing performance impacts.

Should you implement this in your own Shopware 6 environment, remember to adapt the batch size and time range to fit your use case. With these tools in hand, you're well-equipped to manage order data programmatically, allowing for a smooth and automated workflow.

I hope this guide has illuminated the process for you. Should you have any further questions on Shopware 6's API or need more complex examples, feel free to reach out or consult the Shopware

About

Software Developer & Consultant specializing in JavaScript, TypeScript, and modern web technologies.

Share this article