Felix Astner
JavaScript, Magento and other Software
Felix Astner

How to Retrieve 'Paid' Orders in Shopware 6

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.

<?php

namespace Plugin\Service\ScheduledTask;

use DateTime;
use Psr\Log\LoggerInterface;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;

class MyLovelyClass
{
    private EntityRepositoryInterface $orderRepository;
    private LoggerInterface $logger;

    // Constructor and other methods...
}

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'.

// Method within MyLovelyClass

public function getAndExecutePaidOrders(Context $context): void
{
    // Random date for recent orders
    $startDay = new DateTime();
    $startDay->modify('-3 weeks');

    $criteria->addFilter(
        new MultiFilter(
            MultiFilter::CONNECTION_AND,
            [
                /**
                 * A random other filter
                 */
                new RangeFilter(
                    'orderDate',
                    [RangeFilter::GTE => $startDay->format('Y-m-d H:i:s')]
                ),

                /**
                 * The filter for the state of the payment
                 */
                new EqualsFilter(
                    'transactions.stateMachineState.technicalName',
                    'paid' // <-- state
                )
            ]
        )
    );
    
    // Simpler alternative: using the state filter without other filters:
    // $criteria->addFilter(new EqualsFilter('transactions.stateMachineState.technicalName', 'paid'))


}

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.

// Pagination setup and loop within the method

$criteria->setLimit(50); // Adjust batch size as needed

$offset = 0;
do {
    // Fetching orders and processing them
} 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


profile

Felix Astner

As a software developer, I bring a specialized focus in web technologies, enriched by my interests in C++, AI, and computer theory. If you're in need of any freelance services, expert training, or insightful consulting, I encourage you to connect with me.

HomePrivacyImpressum