Magento 2 – How to Retrieve a Random Product from a Random Category

categorycategory-productsmagento2.2.2product-attributerandom

Magento 2.2, developing a custom theme whose parent is Magento/blank.

I intend to create a module which generates a random discount weekly.

Firstly, I must retrieve a random product from a particular sub-category. This data will be utilised on the backend. I must then store its information for a week.

For now, though, I'm only looking for a way to create a model from the information.

There are various answers for Magento 1.x, utilising the rand() function, but I haven't discovered any clear description for Magento 2.

Here is the class, based on Thiago's answer:

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Magento\Framework\Console\Cli;

class CreateDiscount extends Command{

    protected $_productCollectionFactory;
    protected $_categoryFactory;

    public function __construct(
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
        \Magento\Catalog\Model\CategoryFactory $categoryFactory,
        \Magento\Framework\View\Element\Template\Context $context
    ) {
        $this->_categoryFactory = $categoryFactory;
        $this->_productCollectionFactory = $productCollectionFactory;
        parent::__construct($context);
    }

    /**
     * @var $categoryId
     */
    public function getRandomCategoryId() {
        $categoryId = rand(2, 4);
        settype($categoryId, "string");
        return $categoryId;
    }

    /**
     * @param int $categoryId
     */
    public function getRandomProduct($categoryId)
    {
        $products = $this->productRepository->getList($this->getProductSearchCriteria($categoryId));
        $randomId = array_rand($products->getItems(), 1);
        $productItems = $products->getItems();
        return $productItems[$randomId];
    }

    /**
     * @param $categoryId
     * @return \Magento\Framework\Api\SearchCriteria
     */
    private function getProductSearchCriteria($categoryId)
    {
        $searchCriteria = $this->searchCriteriaBuilder
            ->addFilter('category_id', $categoryId)
            ->create();
        return $searchCriteria;
    }

    public function randomProduct()
    {
        // Find a random product
        $product = $this->getRandomProduct($this->getRandomCategoryId());
        $sku = $product->getSku();
    }
}

Best Answer

The best approach (Good practice) is using Interfaces

/**
 * @param int $categoryId
 */
public function getRandomProduct(categoryId)
{
    $products = $this->productRepository->getList($this->getProductSearchCriteria($categoryId));
    $randomId = array_rand($products->getItems(), 1);
    $productItems = $products->getItems();
    return $productItems[$randomId];

}

/**
 * @param $categoryId
 * @return \Magento\Framework\Api\SearchCriteria
 */
private function getProductSearchCriteria($categoryId)
{
    $searchCriteria = $this->searchCriteriaBuilder
        ->addFilter('category_id', $categoryId)
        ->create();
    return $searchCriteria;
}

You should avoid using CollectionFactories and use the respective RepositoryInterface

For now, there is no way to sort items randonly check at Magento\Framework\Api\SortOrder