0

I've been experimenting with SearchCriteriaBuilder but I can't seem to get the syntax right to apply multiple sort.

I've tried this

$this->searchCriteriaBuilder->addFilter(EntryInterface::STATUS, 1, 'eq');
$sort = [];
$sort[] = $this->sortOrder->setField(EntryInterface::COUNTRY)
    ->setDirection(SortOrder::SORT_ASC);
$sort[] = $this->sortOrder->setField(EntryInterface::SORT)
    ->setDirection(SortOrder::SORT_ASC);

$this->searchCriteriaBuilder->setSortOrders($sort);
$searchCriteria = $this->searchCriteriaBuilder->create();
return $this->entryRepositoryInterface->getList($searchCriteria)->getItems();

And this...

$this->searchCriteriaBuilder->addFilter(EntryInterface::STATUS, 1, 'eq');
$sortOne = $this->sortOrder->setField(EntryInterface::COUNTRY)
    ->setDirection(SortOrder::SORT_ASC);
$sortTwo = $this->sortOrder->setField(EntryInterface::SORT)
    ->setDirection(SortOrder::SORT_ASC);

$this->searchCriteriaBuilder->setSortOrders([$sortOne, $sortTwo]);
$searchCriteria = $this->searchCriteriaBuilder->create();
return $this->entryRepositoryInterface->getList($searchCriteria)->getItems();

One more I tried

[...]
$this->searchCriteriaBuilder->setSortOrders([$sortOne]);
$this->searchCriteriaBuilder->setSortOrders([$sortTwo]);
[...]

But only one sort applies.

I've checked the docs and I'm still unsure.

Is it possible to apply multiple sorts?

2 Answers 2

1

The reason it doesn't work for you is that $this->sortOrder is a singleton object. So $sortOne and $sortTwo are referred to the same object.

$sortOne = $this->sortOrder->setField(EntryInterface::COUNTRY)
    ->setDirection(SortOrder::SORT_ASC);
$sortTwo = $this->sortOrder->setField(EntryInterface::SORT)
    ->setDirection(SortOrder::SORT_ASC);

The solution here is to use SortOrderFactory to create $sortOne and $sortTwo object. E.g.

$this->searchCriteriaBuilder->addFilter(EntryInterface::STATUS, 1, 'eq');
$sortOne = $this->sortOrderFactory->create()->setField(EntryInterface::COUNTRY)
    ->setDirection(SortOrder::SORT_ASC);
$sortTwo = $this->sortOrderFactory->create()->setField(EntryInterface::SORT)
    ->setDirection(SortOrder::SORT_ASC);

$this->searchCriteriaBuilder->setSortOrders([$sortOne, $sortTwo]);
$searchCriteria = $this->searchCriteriaBuilder->create();
return $this->entryRepositoryInterface->getList($searchCriteria)->getItems();

FYI, I've also created 2 dummy examples at the webroot folder on a default Magento sample data to prove it. See them here

I hope that it helps.

1
  • This answer is 100% correct Apr 25, 2020 at 23:01
0

Full working example based on other answer

use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Api\SortOrder;
use Magento\Framework\Api\SortOrderFactory;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Xigen\Estimator\Api\Data\EntryInterface;
use Xigen\Estimator\Api\EntryRepositoryInterface;

    /**
     * @param \Magento\Framework\App\Helper\Context $context
     * @param \Xigen\Estimator\Api\EntryRepositoryInterface $entryRepositoryInterface
     * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
     * @param \Magento\Framework\Api\SortOrderFactory $sortOrderFactory
     */
    public function __construct(
        Context $context,
        EntryRepositoryInterface $entryRepositoryInterface,
        SearchCriteriaBuilder $searchCriteriaBuilder,
        SortOrderFactory $sortOrderFactory
    ) {
        $this->entryRepositoryInterface = $entryRepositoryInterface;
        $this->sortOrderFactory = $sortOrderFactory;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
        parent::__construct($context);
    }

    /**
     * Get estimates
     * @param country
     * @return array
     */
    public function getEstimates($country = null)
    {
        $this->searchCriteriaBuilder->addFilter(EntryInterface::STATUS, 1, 'eq');

        if ($country) {
            $this->searchCriteriaBuilder->addFilter(EntryInterface::COUNTRY, $country, 'eq');
        }

        $sortOne = $this->sortOrderFactory->create()
            ->setField(EntryInterface::COUNTRY)
            ->setDirection(SortOrder::SORT_ASC);
        $sortTwo = $this->sortOrderFactory->create()
            ->setField(EntryInterface::SORT)
            ->setDirection(SortOrder::SORT_ASC);

        $this->searchCriteriaBuilder->setSortOrders([$sortOne, $sortTwo]);
        $searchCriteria = $this->searchCriteriaBuilder->create();
        return $this->entryRepositoryInterface->getList($searchCriteria)->getItems();
    }

Your Answer

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

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