40

It's pretty basic, but I can’t find a working example on Stackexchange or google. I want to load a product from a helper or block. I already tried some things like:

$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); 

$product = $objectManager->create('\Magento\Catalog\Api\Data\ProductInterface');

$product->get('<SKU>');

$product->getName();

This returns nothing. I also tried loading any available models and API’s, but nothing seems to work with SKU’s.

Dennis van Schaik
  • 964
  • 1
  • 9
  • 22

7 Answers7

85

The correct way, according to Magento 2 service contracts, is using repositories:

$product = $this->productRepositoryInterface->get($sku);

Use Magento\Catalog\Api\ProductRepositoryInterface to get it in your constructor.

Full example:

...
private $productRepository; 
...
public function __construct(
    ...
    \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
    ...
) {
    ...
    $this->productRepository = $productRepository;
    ...
}

public function loadMyProduct($sku)
{
    return $this->productRepository->get($sku);
}
...

Note:

If the product does not exists, this method triggers a NoSuchEntityException error as it would be in the best Magento2 practice.

So, if you need to handle somehow, wrap it in a try/catch block.

Phoenix128_RiccardoT
  • 7,065
  • 2
  • 22
  • 36
  • 9
    This method gives an error when no product is found. So for checking if an product exists, It seems @fschmengler's solution might be the better way to go. – Dennis van Schaik Apr 20 '16 at 11:00
  • 1
    can you pls add more details about Use Magento\Catalog\Api\ProductRepositoryInterface to get it in your constructor.? What shall I do? Thanks a lot – davideghz Dec 16 '16 at 17:17
  • See my updated post – Phoenix128_RiccardoT Dec 16 '16 at 17:25
  • The actual proper Magento 2 way to use service contracts is more complicated. Repository->get() is still a model call which shouldn't be used. The correct way is to use repository->getList() with SearchCriteriaBuilder. See my answer on Orders (pretty much the same method): http://magento.stackexchange.com/questions/140374/magento-2-1-1-how-to-load-order-with-increment-id-using-orderrepository-object/155341#155341 – Jacques Apr 10 '17 at 10:08
  • @JaccoAmersfoort getList should be used for searching purpose only. – Phoenix128_RiccardoT Apr 10 '17 at 10:27
  • @Phoenix128_RiccardoT Check these links: https://github.com/magento/magento2/issues/3534#issuecomment-227413082 and http://alanstorm.com/magento_2_understanding_object_repositories/ – Jacques Apr 10 '17 at 10:38
  • @JaccoAmersfoort, saw it, but I'm not sure it is the Magento suggested way for a single product search. I think Mulderua was just suggesting a way to "search" depending on attributes, I will investigate it. – Phoenix128_RiccardoT Apr 10 '17 at 10:49
  • 1
    @JaccoAmersfoort, I confirm "get" is the right way. In your example it has been suggested because "get" in order repository requires "order id" and that user was looking for "increment id". In that case a getList is the best option, but if you can use "get" you should use it. – Phoenix128_RiccardoT Apr 10 '17 at 10:57
  • @JaccoAmersfoort Why is repository->getList() not a 'model call' while repository->get() is? seems like they are both methods on the same object. – Shawn Northrop Jan 18 '18 at 18:56
  • @Phoenix128_RiccardoT what happens when you inject \Magento\Catalog\Api\ProductRepositoryInterface? This is an interface rather than an actual class. I'm new to Magento but I would have thought to inject Magento\Catalog\Model\ProductRepository which implements the interface. Also, through my digging around / learning I have seen people Injecting *Factories rather than *Repositories, i.e \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory and then creating a collection and adding Filters or whatnot. Should this be avoided? how would you get a Collection with a Repository? – Shawn Northrop Jan 18 '18 at 19:03
  • @ShawnNorthrop, your point is fair. In Magento2 you can "map" an interface to a real class through a mechanism called "preferences" (check di.xml files). The reasons why we should use interfaces instead of classes is beacause it is the nly way to guarantee compatibility on preferences rewrite. – Phoenix128_RiccardoT Jan 22 '18 at 14:16
  • This is great approach but whenever i entered wrong sku. it will thrown exception and break the process. but I have to hide exception & run the process is it possible ?? – Himanshu Nov 05 '18 at 06:17
  • Call to undefined method Magento\Catalog\Api\Data\ProductInterfaceFactory::get() – Sejal Shah Jan 16 '19 at 10:54
  • @Phoenix128_RiccardoT, what if the sku not available, how to catch the exception here? – Jafar Pinjar Dec 06 '19 at 09:43
  • catch (\Magento\Framework\Exception\NoSuchEntityException $e) { – 00-BBB Feb 22 '21 at 16:40
32

Instead of using the object manager directly, inject the ProductFactory:

public function __construct(\Magento\Catalog\Model\ProductFactory $productFactory)
{
    $this->productFactory = $productFactory;
}

Then use it like this:

$product = $this->productFactory->create();
$product->loadByAttribute('sku', $sku);

or to do a full load (the above loads it using a collection):

$product = $this->productFactory->create();
$product->load($product->getIdBySku($sku));
Fabian Schmengler
  • 65,791
  • 25
  • 187
  • 421
  • 7
    Actually while this is still working, using load() and collections is the "Magento 1" way, better use the repository as suggested by @RiccardoT. – Fabian Schmengler Apr 17 '16 at 20:46
  • 1
    Also, your method will return a Product model, whilst using the Repository will give you a Product data model (Api/Data/Product), which is a Product model converted into a dumbed-down DTO. Something to consider, as they're quite different. – nevvermind Apr 18 '16 at 00:02
  • @FabianSchmengler: Tried using $product = $this->productFactory->create(); $product->load($product->getIdBySku($sku)); $product->getThumbnailUrl() to display product thumbnail image, but its not working. – Slimshadddyyy Jan 31 '18 at 07:24
  • 1
    @FabianSchmengler yes recommendation of Repository is good as @RiccardoT answer. but what if i entered wrong sku then it will break whole operation & throw exception, so in this case we must have to depend on productFactory – Himanshu Nov 05 '18 at 06:20
  • @Himanshu catch the exception. And if you need a fresh product instance in that case, you can still create it using the factory – Fabian Schmengler Nov 05 '18 at 17:00
  • 1
    @FabianSchmengler have tried to catch the exception but it is still breaking the same. – Himanshu Nov 06 '18 at 05:21
  • This gives me a memory limit fatal error (mem limit = 2G) :S – treyBake Mar 10 '20 at 14:30
  • @Himanshu To get the exception to work it needs to be like: catch (\Magento\Framework\Exception\NoSuchEntityException $e) { ... – 00-BBB Feb 22 '21 at 16:39
14

I like @phoenix128-riccardot 's answer, but would add an exception, just in case the product does not exist:

try {
    $product = $this->productRepositoryInterface->get($sku);
} catch (\Magento\Framework\Exception\NoSuchEntityException $e){
    // insert your error handling here
}

I was not able to add it as a comment (too low reputation), sorry.

hey
  • 1,137
  • 1
  • 10
  • 27
8

You can try that

$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); 

$productRepository = $objectManager->get('\Magento\Catalog\Model\ProductRepository');
$productObj = $productRepository->get('<SKU>');

echo $productObj->getId();
Nadeem0035
  • 1,227
  • 12
  • 19
5

Try this:

/** @var \Magento\Catalog\Model\ProductFactory $productFactory */
$product = $productFactory->create();
$product->loadByAttribute('sku', 'my sku');

// $product->load($product->getId()); // may need to do this too,
// see \Magento\Framework\Api\AttributeValueFactory\AbstractModel::loadByAttribute
Daniel Ifrim
  • 3,404
  • 2
  • 22
  • 36
  • I need to get the product_id from sku (column of csv) during csv import and save only the product_id..How to achieve? – Sushivam Aug 25 '16 at 09:45
2

Using Dependency Injection (DI)

Here is the example code to get the product information by product Id and SKU in Magento 2 using dependency injection.

In this, we might need to inject the object of the \Magento\Catalog\Model\ProductRepository class in the constructor of our module’s block class and access it from the view ( .phtml ) file.

Sample File Path: app/code/YourCompanyName/YourModuleName/Block/YourCustomBlock.php

<?php
namespace YourCompanyName\YourModuleName\Block;

class YourCustomBlock extends \Magento\Framework\View\Element\Template
{ 
    protected $_productRepository;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context, 
        \Magento\Catalog\Model\ProductRepository $productRepository,
        array $data = []
    ) {
        $this->_productRepository = $productRepository;
        parent::__construct($context, $data);
    }

    public function getProductById($id) {
        return $this->_productRepository->getById($id);
    }

    public function getProductBySku($sku) {
        return $this->_productRepository->get($sku);
    }
}

Now, we can use the functions in our view (.phtml) file as follows.

// get product by id
$product = $block->getProductById(15);

// get product by sku
$product = $block->getProductBySku('MT12');

echo $product->getEntityId() . '<br>';
echo $product->getName() . '<br>';
echo $product->getSKU() . '<br>';
echo $product->getPrice() . '<br>';
echo $product->getSpecialPrice() . '<br>';
echo $product->getTypeId() . '<br>';
echo $product->getProductUrl() . '<br>';

Using Object Manager

Here is the example code to get the product information by product id and SKU in Magento 2 using object manager.

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();

$productRepository = $objectManager->get('\Magento\Catalog\Model\ProductRepository');

// get product by product id 
$product = $productRepository->getById(15);

// get product by product sku 
$product = $productRepository->get('MT12');

echo $product->getEntityId() . '<br>';
echo $product->getName() . '<br>';
echo $product->getSKU() . '<br>';
echo $product->getPrice() . '<br>';
echo $product->getSpecialPrice() . '<br>';
echo $product->getTypeId() . '<br>';
echo $product->getProductUrl() . '<br>';
-2
<?php
use Magento\Framework\App\Bootstrap;
require __DIR__ . '/app/bootstrap.php';
$bootstrap = Bootstrap::create(BP, $_SERVER);
$obj = $bootstrap->getObjectManager();
$state = $obj->get('Magento\Framework\App\State');
$state->setAreaCode('frontend');


$sku ='24-MB01';
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$productObject = $objectManager->get('Magento\Catalog\Model\Product');
$product = $productObject->loadByAttribute('sku', $sku);
echo $product->getName();

?>
Nagaraju Kasa
  • 5,856
  • 6
  • 53
  • 113