12

I am trying the following code to get the IDs of all the simple products which are children of $collection, which I know to be a collection of configurable products.

foreach($collection as $_product) {
    $_children = $_product->getTypeInstance()->getUsedProductIds($_product);
    print_r($_children);
}

However, all the arrays I am getting are empty. Am I doing something wrong?

4
  • Does your collection have something in it?
    – Aedonis
    May 31 '16 at 22:21
  • Yes, multiple products
    – b_pcakes
    May 31 '16 at 22:32
  • 2
    Try using this $_children = $_product->getTypeInstance()->getUsedProducts($_product); See if you are getting anything.
    – Aedonis
    Jun 1 '16 at 8:24
  • I have actually already tried that, as well as getUsedProductCollection
    – b_pcakes
    Jun 1 '16 at 16:38
29

You can print your child products ids ( of configurable products) via making a small change to your code as follow

foreach($collection as $_product) {
        $logger->info("Here are Parent Product Name".$_product->getName());
        $_children = $_product->getTypeInstance()->getUsedProducts($_product);
        foreach ($_children as $child){
            $logger->info("Here are your child Product Ids ".$child->getID());
        }
    }

After this look at to your log files and you will have your child IDS.

1
  • For Magento 2.2.6 din't worked, instead used: $product->getTypeId() Jun 7 '19 at 18:37
23

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.

3
  • this seems to be horribly slower though unless I'm doing something wrong...
    – igrossiter
    Aug 8 '18 at 9:55
  • 2
    Need to investigate but linkManagement seems not loading all child fields like "special_price" so is better for architecture but seem not very usefull in some cases. $_product->getTypeInstance()->getUsedProducts($_product); works correctly Nov 30 '18 at 10:22
  • Man, don't you wish Magento would think to implement a $item->getChildren() method?
    – snez
    Jun 23 at 15:44
3

You can just call below method,

     foreach($collection as $_product) {
            $_configChild = $_product->getTypeInstance()->getUsedProductIds($_product);
            $getChildId = array();
            foreach ($_configChild as $child){
                $getChildId[] = $child;
            }
            echo "<pre>";print_r($getChildId);
        }

Above $getChildId display all simple Product id.

2

To get the actual child product objects (not just strings of their IDs) use this:

$childProducts = $product->getTypeInstance()->getUsedProducts($product);

To get their IDs or other properties, use the above with a loop:

foreach ($childProducts as $childProduct) {
    echo $childProduct->getId();
}
1

Another way to achieve this is to use the getChildrenIds method.

$children = $cProductTypeInstance->getChildrenIds($this->currentProductObj->getId());

    // Get all the existing child and add it to associate Id too
    $existingChildrenIds = array();
    foreach ($children as $childIds) {
        foreach ($childIds as $child){
            $existingChildrenIds[] = $child;
        }
    }
0

Very often you want to get not only ID, but also name attribute and so on. The call $product->getTypeInstance()->getUsedProducts($product) returns array of simple products without prepared name attribute.

You should use next code sniped to get attributes which you want:

$children = Mage::getModel('catalog/product_type_configurable')->getUsedProductCollection($configurable);
$children->addAttributeToSelect('sku')
    ->addAttributeToSelect('name')
    ->addAttributeToSelect('attribute_set_id')
    ->addAttributeToSelect('type_id');

There is a simpler way to achieve the same. Use next one code snippet:

$children = Mage::getModel('catalog/product_type_configurable')->getUsedProductCollection($configurable);
$children->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes());

This prepares the product collection to load the necessary data to display prices, the product link and any attributes configured as "used in product listing", but not more.

0

To get all simple children including out of stock products use:

$children = $product
          ->getTypeInstance()
          ->getChildrenIds($product->getId());

          print_r($children);

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.