Magento 2: Apply visibility and status filters on product collection

For getting product collection with status enable and visibility:

you have to keep below code in block file.

protected $productCollectionFactory;
protected $productVisibility;
protected $productStatus;

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,        
    \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
    \Magento\Catalog\Model\Product\Attribute\Source\Status $productStatus,
    \Magento\Catalog\Model\Product\Visibility $productVisibility,
    array $data = []
)
{
    $this->productCollectionFactory = $productCollectionFactory;
    $this->productStatus = $productStatus;
    $this->productVisibility = $productVisibility;
    parent::__construct($context, $data);
}

public function getProductCollection()
{
    $collection = $this->productCollectionFactory->create();
    $collection->addAttributeToFilter('status', ['in' => $this->productStatus->getVisibleStatusIds()]);
    $collection->setVisibility($this->productVisibility->getVisibleInSiteIds());
    return $collection;
}

Above code working for visibility type for:

  • VISIBILITY_IN_SEARCH
  • VISIBILITY_IN_CATALOG
  • VISIBILITY_BOTH

This should work for you:

    $collection = $this->collectionFactory->create();

    $collection->addAttributeToFilter('status', ['in' => $this->productStatus->getVisibleStatusIds()]);
    $collection->setVisibility($this->productVisibility->getVisibleInSiteIds());

Used classes are:

/**
 * @var \Magento\Catalog\Model\Resource\Product\CollectionFactory
 */
protected $collectionFactory;

/**
 * @var \Magento\Catalog\Model\Product\Attribute\Source\Status
 */
protected $productStatus;

/**
 * @var \Magento\Catalog\Model\Product\Visibility
 */
protected $productVisibility;

Review these classes to check another methods to get possible status or visibility values.

However, review concept of repositories, as far as I saw Magento 2 recommends using repository to access product data instead of using collection. For example:

$searchCriteria = $this->searchCriteriaBuilder->create();

$products = $this->productRepository->getList($searchCriteria)->getItems();