0

As per title.

This what I've done:

    $filterCode = new Filter();
    $filterCode->setField('SpecialCode')
        ->setValue('')
        ->setConditionType('null');
    $filterItemId = new Filter();
    $filterItemId->setField('ItemId')
        ->setValue('')
        ->setConditionType('null');

    $searchCriteria = $this->searchCriteriaBuilder
        ->addFilters([$filterCode, $filterItemId])
        ->create();
    $customItems = $this->customItemRepository->getList($searchCriteria)->getItems();

What I'm getting is a collection of items with NULL ItemID or NULL SpecialCode (or I have no idea what I'm getting), when what I want is more like this:

select * from ItemRepository where ItemId is null and SpecialCode is null;  //I'm pretty sure what I would get from this

How do I create multiple filters and set conditional ANDfor those filters?

  • Not that this is the cause of your issues, but you shouldn't be instantiating PHP classes with the 'new' keyword, such as new Filter(). – Shawn Abramson May 2 '18 at 4:36
  • How do we do this then? @ShawnAbramson – farid JAD7 May 2 '18 at 4:57
  • Please see my answer below. – Shawn Abramson May 2 '18 at 5:01
2

In the constructor, notice that I appended the word "Factory" to the classname of the collection. This is a non-existent factory class that Magento will actually create for you. In the function, where I call $this->collectionFactory->create();, that tells Magento to give me a new instance of the collection. It's the same as doing new \My\Custom\Collection(); except for the fact that you do not lose any functionality that might be provided by Magento's object manager. Following this example, this is the same way you would deal with getting rid of new Filter() and instead pass FilterFactory as a constructor argument.

Anyways, with that out of the way, you really don't need the search criteria builder for this task. Simply replace \My\Custom\Collection with the actual name of your collection and this will work.

Reminder: when you create the constructor in your class, if your class extends any other PHP class, don't forget to include the parent classes constructor args and pass them back up to the parent class.

The call to the collection with the filters, as shown, will give you a query exactly as you asked for above.

<?php

class MyCustomClass
{
    /**
     * @var \My\Custom\CollectionFactory
     */
    private $collectionFactory;

    /**
     * MyCustomClass constructor.
     *
     * @param \My\Custom\CollectionFactory $collectionFactory
     */
    public function __construct(
        \My\Custom\CollectionFactory $collectionFactory
    ) {
        $this->collectionFactory = $collectionFactory;
    }

    /**
     * @return \My\Custom\Collection
     */
    public function getFilteredCollection()
    {
        /** @var \My\Custom\Collection $collection */
        $collection = $this->collectionFactory->create();
        $collection->addFieldToSelect('*');
        $collection->addFieldToFilter('ItemId', ['null' => true]);
        $collection->addFieldToFilter('SpecialCode', ['null' => true]);

        return $collection;
    }
}

Version of answer using the SearchCriteriaBuiler. Also, please note that since I know nothing of your custom collection, I wrote this with the OrderItemRepository. You will just need to replace the repository with your own of course and obviously switch out the field names.

<?php 

class MyCustomClass
{
    /**
     * @var \Magento\Sales\Api\OrderItemRepositoryInterface
     */
    private $orderItemRepository;

    /**
     * @var \Magento\Framework\Api\SearchCriteriaBuilder
     */
    private $searchCriteriaBuilder;

    /**
     * MyCustomClass constructor.
     *
     * @param \Magento\Sales\Api\OrderItemRepositoryInterface         $orderItemRepository
     * @param \Magento\Framework\Api\SearchCriteriaBuilderFactory     $searchCriteriaBuilderFactory
     */
    public function __construct(
        \Magento\Sales\Api\OrderItemRepositoryInterface $orderItemRepository,
        \Magento\Framework\Api\SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory
    ) {
        $this->orderItemRepository = $orderItemRepository;
        $this->searchCriteriaBuilder = $searchCriteriaBuilderFactory->create();
    }

    /**
     * @return \Magento\Sales\Api\Data\OrderItemSearchResultInterface
     */
    public function getFilteredList()
    {
        $this->searchCriteriaBuilder->addFilter('applied_rule_ids', true, 'null');
        $this->searchCriteriaBuilder->addFilter('weight', true, 'null');
        $collection = $this->orderItemRepository->getList(
            $this->searchCriteriaBuilder->create()
        );

        return $collection;
    }
}
  • So there is no way to do this via repository? I have multiple other classes that does some operation on different repositories, it would be weird if for this one functionality to change on using factory instead of repository. – farid JAD7 May 2 '18 at 5:14
  • I am not a fan of the SearchCriteriaBuiler and Filter classes. Using the collection is much easier, less code, easier to read, etc. I'll see if I can whip something up using the methods you want, with filters. – Shawn Abramson May 2 '18 at 5:18
  • Please don't forget to mark this answer as accepted once you get to test. – Shawn Abramson May 2 '18 at 6:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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