PHP: Call to a member function is() on null

This happens when trying to access methods on objects that are not instantiated. Always check if an object is instantiated before trying to use it.

838 views
d

By. Jacob

Edited: 2023-07-21 06:37

php.CRITICAL: Uncaught Error: Call to a member function is() on null {"exception":"[object] (Error(code: 0): Call to a member function is() on null at /srv/shopware/vendor/shopware/core/Framework/DataAbstractionLayer/Write/Command/WriteCommandQueue.php:151)"} []

This is actually a fairly common problem, but the involved methods differ although the cause is the same: trying to access a method on an object that has not been instantiated yet.

Because of the complex environment and combinations an object might be used in, developers may want to implement a suitable number of checks and exception messages to describe what has happened; it is not enough to rely on the default. E.g. Call to a member function foe() on null is not very helpful and can cause more confusion.

In one case, I had this happen when trying to create a new custom made entity from a plugin in Shopware 6. In the "front end" of things it might show as a 500 Internal Server Error, as was the case in Shopware.

How to fix the problem

If you read the message carefully then you will see that it tells you the exact line number where the error occurred. In my case you can tell that it happened in a Shopware core file. Specifically line 151 of WriteCommandQueue.php

Trying to access "member functions on null" is a mistake I have encountered many times in Shopware-land. A likely cause is that developers often forget to check whether an object is properly instantiated before trying to access it – but it is a surprise for this error to be in a core file. Of course, another possibility is simply bad design on Shopware's part; the system may be so complex that it is easy for plugin developers to trigger such errors, and Shopware has not yet implemented the proper error messaging to explain it to developers.

But this is a core class you might add – this should work! Yes. It should. But developers make mistakes and overlook things. Although, I am not certain this is a Shopware error, I know there at least is a lack of describing the error properly to plugin developers.

Simply adding a check for null fixed it in my case – as it has in numerous of other circumstances. It can also happen as a result of issues with the cache in some cases, but then doing a manual deletion of the cache tends to fix it.

My other hunch is that a referenced database table field is missing in the plugin code, and because of that unexpected situation Shopware is producing an error without really explaining what the problem is. It can often be hard to know for sure without inspecting the involved code thoroughly – both the core Shopware code and that of the plugin. This is my next step, because I have seen custom entities that worked, and as such it is fair to assume there is an error in the plugin. What is difficult to know is whether it should be a fatal error.

Anyway, to fix the problem you may try and add a temporary check for null if the context tolerates it. In my case:

nano +151 /var/www/shopware/vendor/shopware/core/Framework/DataAbstractionLayer/Write/Command/WriteCommandQueue.php

Add a check for null to the if statement:

if (null !== $storage && !$storage->is(Required::class)) {
  return null;
}

The method already makes a return if the is method fails, as such we see that a return is handled somewhere from the outside, meaning we can try it to see if it's tolerated on missing objects.

In many cases you will be dealing with a situation where a developer simply forgot to check if the relevant object was instantiated before accessing a member function – they may have made the assumption that it would always be instantiated and therefore no check is needed. In complex environments we can not know for sure, and such assumptions will be more risky. There can potentially be future or outside factors causing an object not to be instantiated that we do not know about.

In general it is probably a good practice to always check that an object is instantiated before using it, and if not, a proper error message should describe what may have triggered the problem.

Important note Always check if the problem is in your own code, in the plugin, or dependency that you are using before deciding to edit files not your own. E.g. core CMS files.

How to describe the problem properly

Often you will not be able to tell exactly what went wrong, but you can still provide some helpful directions to the developers. E.g. If some code fails to open a file, it can be due to incorrect file permissions, or maybe the file does not exist? Provide that information to the developer, because it is very helpful.

Even throwing a basic PHP exception is better than relying on the default PHP error. E.g:

if (null !== $storage) {
  throw new Exception('The $storage object was not defined; maybe a database table field was missing in the code of a plugin?');
}
if (!$storage->is(Required::class)) {
  return null;
}

Note. The above is just an example; I have no idea whether the above message would be relevant in the context of the specific error I encountered in Shopware.

Tell us what you think:

  1. How to create a custom error handler for PHP that handles non-fetal errors.
  2. The fread function can be dangerous when used inside a loop in PHP, find out how to secure it in this article.
  3. How to show or hide error messages in PHP. There are several ways to do this; from within the PHP scripts themselves, from php.ini, or from changing Apache configuration files.
  4. E_STRICT will only show you warnings about deprecated PHP features and things that might not be future-proof, it will not show you notices or warnings; E_ALL includes everything, and that includes E_STRICT messages.
  5. Developers can trigger custom PHP error messages using the trigger_error function; but throwing an exception is often better.

More in: PHP Errors