How to resolve “call to a member function get() on null” error

How to resolve “call to a member function get() on null” error

Let's learn about the "call to member function on null" error, which occurs when an object calls a function, and it fails.

“Call to a member function get() on null” — we’ve assuredly come across this error before, but what does it mean, and how can you fix it?

Let’s first think about how this error occurs. A crucial aspect of the statement is the “on null” part.

This tells you, simply, that you are calling a function “on null”, meaning this:

$item->get();

...means that the function call of get() is being called on an object ($item) doesn't exist (is null). This means that $item === null.

PHP code example

Let’s look at an example of this in real life, using common errors that occur in Magento. However, this error could be thrown in any other PHP application as well, including Laravel, Drupal, etc.

Here’s a block of code from a PHTML template:

<?php
 
/* @var \Magento\Catalog\Block\Product\View $block */
$product = $block->getProduct();
$category = $product->getCategoryId();
...

Let’s assume that executing this block of code returns the following error:

Call to a member function getCategoryId() on null

Why does this happen? Well, here’s what’s happening when the code passes through PHP’s parser:

<?php
 
/* @var \Magento\Catalog\Block\Product\View $block */
$product = $block->getProduct(); // $product is evaluating to null
$category = $product->getCategoryId(); // null->getCategory() throws an error
...

The code tries to grab the category ID with the getCategoryId() function, but since $product is null, it throws the error. The above snippet essentially evaluates to:

$product = null;
$category = $product->getCategoryId(); // error!

This means that the root of the error isn’t the call to getCategoryId(), but rather that $product = null.

Issues within looping code

This same issue can occur anywhere, including within iterable code, such as foreach loops. Another common scenario is retrieving a collection of objects from the database, and then trying to retrieve a child object within an iteration of the loop.

Let’s look at another example, this time from within a loop:

<?php $allShipmentItems = $shipmentItems->getAllItems(); ?>
<?php foreach ($allShipmentItems as $shipmentItem): ?>
    <?php $parentItem = $shipmentItem->getOrderItem()->getParentItem(); ?>
    <?php if (!$parentItem): ?>
        <tbody>
            <?= $block->getItemHtml($shipmentItem) ?>
        </tbody>
    <?php endif; ?>
<?php endforeach; ?>

And this returns the error:

Call to a member function getParentItem() on null

Again, when the call to the getParentItem() function is executed, PHP bails out of the script, since the call to $shipmentItem->getOrderItem() is evaluating to null.

This means that we need to find out why getOrderItem() is returning null, so we need to inspect that function.

Stepping into the function

In the code we just looked at, we can step into the getOrderItem() function to find out what is going on. In Magento, this will lead us to the method at Magento\Sales\Model\Order\Shipment\Item::getOrderItem().

This code checks if the _orderItem property exists, and if it does not, it executes some code to grab the order from the database, using one of two conditions:

vendor/magento/module-sales/Model/Order/Shipment/Item.php
/**
 * Retrieve order item instance
 *
 * @return \Magento\Sales\Model\Order\Item
 */
public function getOrderItem()
{
    if (null === $this->_orderItem) {
        if ($this->getShipment()) {
            $this->_orderItem = $this->getShipment()->getOrder()->getItemById($this->getOrderItemId());
        } else {
            $this->_orderItem = $this->_orderItemFactory->create()->load($this->getOrderItemId());
        }
    }
    return $this->_orderItem;
}

If a shipment is found on the ordered item, it executes the first line of the conditional. Otherwise, it falls back to attempting to load the order item from the order item ID, using the OrderItemFactory class.

Set a breakpoint with Xdebug

Xdebug can be extremely helpful with identifying and resolving the error. Now that we’ve found the offending code, we can use Xdebug to confirm the issue.

Since we are concerned about the value of the _orderItem property, we should set a breakpoint within this function and inspect the results of this property’s assignment. This will help to tell us which conditional is executing, so we can dig a bit deeper into that related code.

When executed, you will be able to clearly see that the first line which attempts to retrieve the order information is the culprit. Now, we can dig deeper into it, by stepping into that method.

Since we know that the order_item_id is populated, we can step back out to the getItemById() function and find out what is going on there.

vendor/magento/module-sales/Model/Order.php
/**
 * Gets order item by given ID.
 *
 * @param int $itemId
 * @return \Magento\Framework\DataObject|null
 */
public function getItemById($itemId)
{
    $items = $this->getItems();
 
    if (isset($items[$itemId])) {
        return $items[$itemId];
    }
 
    return null;
}

And when we walk through this code, we can see that $this->getItems() evaluates to null. This means that this code is the culprit, and is the underlying issue at play.

Conclusion

In this situation, it appears that the lack of an items property on the object is a data integrity error.

It’s possible that a migration of this order’s data failed, or that the order item data got corrupted. In any case, we found out why the attempt to grab the parent data with $shipmentItem->getOrderItem()->getParentItem() failed, and it’s because the order item didn’t exist in the first place (or rather, is null).

Hopefully this article has helped explain how a Call to a member function get() on null error gets thrown, what goes on when the PHP code executes, and how to take steps to resolve the issue!

How you resolve it is up to you, but more often than not the issue is caused by missing data, or corrupt underlying data content. If it isn’t caused by loads out of the database, the most likely culprit is improper logic within the parent function which is calling the underlying method, which can also be resolved using a tool like Xdebug.

Next Steps

  1. Understand the Magento 2 Request-Response Lifecycle (Article)
  2. Start learning Magento with the Magento 2 Coding Jumpstart Course (Free, 13,000+ Students)
  3. Take the Magento 2 Coding Kickstart Course to truly learn Magento (700+ Students)