The answers to this question are wrong. Although their implementations might work, it's not the proper way to handle this. The correct way to do this is by using Magentos' service contracts and data models.
In this case, it's the Magento\ConfigurableProduct\Api\LinkManagementInterface
Service contract you need.
A small example of code I'm using in a console command:
<?php
namespace Vendor\Module\Console;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\ConfigurableProduct\Api\LinkManagementInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\App\State;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class UpdateChildProducts
* @package Vendor\Module\Console
*/
class UpdateChildProducts extends Command
{
/**
* @var ProductRepositoryInterface
*/
protected $productRepository;
/**
* @var SearchCriteriaBuilder
*/
protected $searchCriteriaBuilder;
/**
* @var LinkManagementInterface
*/
protected $linkManagement;
/**
* @var State
*/
protected $state;
/**
* UpdateChildProducts constructor.
* @param State $state
* @param LinkManagementInterface $linkManagement
* @param ProductRepositoryInterface $productRepository
* @param SearchCriteriaBuilder $searchCriteriaBuilder
* @param string $name
*/
public function __construct(
State $state,
LinkManagementInterface $linkManagement,
ProductRepositoryInterface $productRepository,
SearchCriteriaBuilder $searchCriteriaBuilder,
$name = 'update_child_products'
) {
$this->state = $state;
$this->linkManagement = $linkManagement;
$this->productRepository = $productRepository;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
parent::__construct($name);
}
/**
* Configure this command
*/
protected function configure()
{
$this->setName('example:update_child_products');
$this->setDescription('Iterate over all configurable products and show their children count.');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
// Set area code
try {
$this->state->setAreaCode('adminhtml');
} catch (\Exception $e) {
// Fail silently ...
}
$searchCriteria = $this->searchCriteriaBuilder
->addFilter('type_id', 'configurable')
->create();
$configurableProducts = $this->productRepository->getList($searchCriteria);
$output->writeln(sprintf('Found %d configurable products ...', $configurableProducts->getTotalCount()));
foreach ($configurableProducts->getItems() as $configurableProduct) {
$childProducts = $this->linkManagement->getChildren($configurableProduct->getSku());
$output->writeln(
sprintf('Found %d children for %s', count($childProducts), $configurableProduct->getSku())
);
}
}
}
Magento 2 isn't very consistent with it's own code since the majority of the code is ported from Magento 1. That's why you still see leftovers of inheritance-based models and their methods (like getTypeInstance()
). If you want to build future-proof Magento 2 code, use service contracts and data models as much as possible.
$_children = $_product->getTypeInstance()->getUsedProducts($_product);
See if you are getting anything.getUsedProductCollection