PHP 8.2 is coming, and we’re getting ready!

In a couple of months, PHP 8.2 is scheduled to be released in November 2022. This new version will bring improvements such as increased performance and stability, but it will also introduce some important breaking changes. One of the most important changes is the (fairly unexpected) deprecation of a feature which has been available for a decade, and that we have used extensively to improve the performance of some of our solutions, such as our Aelia Currency Switcher, Aelia Prices by Country, and some of the addons we wrote for plugins like Subscriptions, Product Bundles or Composite Products.

This is going to be a (long) technical post. We’re going to discuss some aspects of PHP 8.2, explaining the improvements we made to deal with the change, as well as the possible issues that you might encounter. If you’re not familiar with the PHP programming language and the technical aspects of WordPress and WooCommerce, we recommend to involve your developer, who can help you understanding the topics that we will cover.

In a nutshell (TL;DR)

  1. We had to update our plugins to handle the changes in PHP 8.2.
  2. Before installing the new versions of the plugins, which include the changes, we strongly recommend to read the upgrade instructions. They also explain what to do if anything goes wrong.
  3. If you have any questions, you can reach out to us at any time.

Breaking change in PHP 8.2 – Deprecation of dynamic properties

PHP 8.2 will deprecate a feature called “dynamic properties“. The purpose of that feature is to allow “tacking” properties, which are like attributes, to objects that don’t normally have them. This feature comes in handy when one has to “append” some additional information to an object, such as a status to keep track of some custom processing.

The Aelia plugins have used this technique from their first release, as a way to improve performance and avoid redundant processing of entities such as products. For example, our flagship plugin, the Aelia Currency Switcher, uses dynamic properties track progress of price conversion and to store a copy of the calculated prices, without having to determine them every time someone tries to fetch them. Below is a simplified example of the flow, for illustration purposes:

    1. An entity fetches the price from a product instance (regular, sale or final price)
    2. The Currency Switcher intercepts the call.
    3. The Currency Switcher checks if the product has properties (attributes) like regular_price, sale_price, price and currency. Normally, these attributes don’t exist against a product instance. The price conversion process adds them (see the next step).
    4. The Currency Switcher can’t find the properties. Due to that, calculates the prices in the appropriate currencies and “tacks” them against the product instance, together with their currency. These are the dynamic properties mentioned earlier. From this moment on, the product has a regular_price, sale_price, price and currency properties.
    5. An entity (it could be the same one as before, or another one) fetches the price from a product instance again.
    6. The Currency Switcher intercepts the call.
    7. The Currency Switcher checks if the product has properties like regular_price, sale_price, price and currency. The properties exist, having been added earlier. If the currency property matches the active currency, then the Currency Switcher doesn’t do anything else, because it already calculated the prices in that currency. This saves a significant amount of processing time and greatly improves the performance.

Our approach has been working fine for years, and we had no plans to change this logic, as it’s simple and effective. However, we have to review it, due to a change made by one of the core PHP developers, who  decided that dynamic properties had to be removed or, better, disabled by default (more on this in the following paragraph). The rationale behind the developer’s decision is that he considered them a feature that is rarely used intentionally (see https://wiki.php.net/rfc/deprecate_dynamic_properties). Ours was one of those intentional use cases, and the breaking change affects most of our plugins.

What happens if one uses dynamic properties with PHP 8.2 and later?

Starting with PHP 8.2, any attempt to use dynamic properties will result in a “deprecated” notice. These warnings don’t affect the code execution (i.e. the code works fine), but they can appear on screen, if PHP isn’t configured to hide them, as well as log files. Although any logic that relies on them keeps working, these notices can quickly become a nuisance.

Things will get more serious with PHP 9.0. That version will disallow dynamic properties by default, and throw a fatal error if one tries to use that feature with classes that haven’t been explicitly “tagged” to accept these properties. If one absolutely needs that feature, one can add a special “tag” to the class to restore that functionality. This is why we said that dynamic properties are “disabled by default”.

The challenges

The deprecation of dynamic properties introduced several challenges:

    1. Despite what the PHP core developer thought, the solution of adding a special tag to classes to restore dynamic properties is not practical.
      To do that, one would need to modify the code where the classes are declared. However, if a developer could do that, one could simply declare the necessary properties directly to the class definition, instead of creating new ones dynamically. Dynamic properties are useful for classes that can’t be modified, such as the ones that WooCommerce provides. Due to that, we can’t add tags to restore the feature.
    2. PHP 8.2 introduces some new tools, such as the WeakMap, that developers can use in place of dynamic properties. However, these tools aren’t available in earlier PHP versions.
      Due to that, the deprecation creates a net separation that requires different approaches from one version to the next:
      1. Up until PHP 8.1, one can use dynamic properties, and there isn’t any viable alternative approach. There are some “workarounds”, but they require at least PHP 7.4, and aren’t very user friendly, nor particularly performing.
      2. From PHP 8.2, one can use the WeakMap class, but no dynamic properties, unless one can modify the classes to which these properties should be applied (which we can’t do).
      This means that one would have to implement two different ways to handle dynamic properties, and run the appropriate one depending on the PHP version.
    3. As mentioned, we used dynamic properties extensively in our solutions.
      We didn’t expect a core feature, such as dynamic properties, to be removed from PHP, therefore we didn’t keep track of all the places where we used them over the course of the past 9 years. Due to that, we have to review all our plugins, in order to discover where we used them, and alter the logic to be both backward- and forward-compatible.

Our approach to ensure maximum compatibility

Over the past couple of months, we evaluated a series of possible solutions to ensure that our products will keep working with PHP versions before and after 8.2, and made two changes:

    1. We updated our in-house framework, the Aelia Foundation Classes, to include a strategy to automatically switch from dynamic properties to the new approach. The two methods are cross-compatible and interchangeable, and the switch is seamless. Version 2.3.0.220730 of the Aelia Foundation Classes, which will be the minimum version required by most of our plugins, already includes this new logic.
    2. We reviewed the whole code base of all our plugins to spot dynamic properties, and updated it to use the new method we added to the Aelia Foundation Classes.

An important aspect of these changes is that, despite being extensive, the new logic is still 100% backward compatible, and equivalent to the previous one. In simple terms, we made a lot of changes to ensure that all our plugins worked exactly like they did before. For this reason, the version number shows a minor update (e.g. in the case of the Currency Switcher, the version goes from 4.13 to 4.14, rather than 5.0).

What you need to know

Since we used dynamic properties extensively, we had to make several changes to many of the components that make our solutions. Our target was to implement the necessary changes in such a way that the underlying logic remained the same as the original one in terms of functionality, reliability and performance. We put all our best effort to reach that goal.

We tested each component individually, then we ran tests on each plugin, and also manually tested each functionality, to ensure that everything works smoothly. Finally, we tested our plugins in different combinations, to verify their cross-compatibility. Our tests were positive, and we’re ready to release the new versions. We will still keep running tests to find possible the edge cases, so that we can address them as they arise.

Below you can find a list of the plugins that we updated to handle the upcoming changes in PHP 8.2. If you’re using any of them, we recommend to read the upgrade instructions before updating them.

Paid solutions

Free addons

This list includes addons for other plugins that, despite our best efforts, still haven’t been updated with native multi-currency support. The addons are provided as a courtesy, free of charge, and they don’t represent a guarantee of compatibility.

Although our tests indicate that our modifications are working correctly, we though appropriate to put together some guidelines to help you with the upgrade, together with a “safety net” in case you come across a scenario that we might not have encountered. To ensure a smooth upgrade, we strongly recommend to read the following instructions before updating the plugins.

Upgrade instructions

The following instructions aim at ensuring a smooth upgrade. We also included the steps to restore a previous version of the plugin, in case you come across an edge case scenario that our tests didn’t cover.

💡 Tip: these are actually the same steps that the WooCommerce Team recommends when updating WooCommerce.

Step 1 – Install the updates on a staging site

    1. Create a staging copy of your site. Most hosting providers offer that feature as part of the hosting plan and they should be able to help you with this step.
    2. Install the new version of the plugin(s) on your staging site. The upgrade process is the usual one: you can simply go to WordPress Admin > Plugins and install the updates from there.
      💡 Tip: you can activate your licence key on the staging site, free of charge (i.e. without using up your activation quota), and get automatic updates on it. You will just have to check that the staging site’s domain matches one of the recognised test domains. For more information, please refer to our documentation: How to manage your licences for the Aelia products (Freemius Service) (section #5).
    3. Check that the staging site is working correctly. Below you can find some test suggestions. Please feel free to perform any of them, depending on your time availability:
    4. View a product on the frontend, and switch between countries (Prices by Country) and currencies (Currency Switcher), to check that the prices are correct.
    5. Edit a product in the backend, to verify that the prices are saved correctly and appear on the frontend.
    6. Add a product to the cart. Switch between countries and currencies, to verify that the prices are correct.
    7. Go to the checkout page. Once again, switch between countries and currencies, to verify that the prices are correct.
    8. Place a test order. Our plugins don’t affect the payment process, but it could be a good idea to place a test order anyway, to be sure that customers can completed their purchases.

Step 2 – Install the updates on the live site

    1. After completing the tests on the staging site, you can upgrade the live site. You can find our recommended steps below:
    2. Take a full backup of your live site. This is an extra safety precaution, to be fully covered. In the unlikely case of emergency, you will be able to restore your backup.
      💡 Tip: most hosting providers offer a backup service. That could be a convenient option to save a copy of your site.
    3. Update the plugins on the live site.
    4. Repeat the tests performed on the staging site (optional, but recommended). The plugins running on the staging and live site are identical, but the environment itself might be different. Some additional checks could be a good idea.

Troubleshooting instructions (just in case!)

If you spot any issue, we recommend the following course of action:

    1. Report the error to us, using our contact form: https://aelia.co/contact/. Please include the details of the error, as well as the name and version of the affected plugin. If you have any screenshots, please include them as well.
    2. If the error occurs on the staging site, simply stop there. Keep the old version on the live site while we look into the issue.
    3. If the error occurs on the live site, you can roll back to a previous version by following the instructions below.

How to download a previous version of a premium plugin

If you purchased one of our products via the Freemius platform, you can download any of the previous versions by following these steps (screenshot below):

    1. Log on your account at https://aelia.co/account.
    2. When the dashboard opens, click on the Downloads on the left.
    3. Click on the “down” arrow on the right of the Download button. This will open a list with all the available versions.
    4. Click on the desired version to download it.

💡 Tip: these instructions apply if you received a licence from the Freemius licensing service. If you are still using a licence from our legacy licensing system, please contact us and we will send you a prior version.

Free plugins

You can download the last version of our free plugins, before we made the changes for PHP 8.2, from the links below:

How to install the previous version of a plugin

After downloading the desired version, you can install it on your site as follows:

    1. Go to WordPress Admin > Plugins.
    2. Click on Add new.
    3. On the page that opens, click on Upload Plugin.
    4. Select the ZIP file you downloaded and confirm the upload. This will install the older version, while preserving all your existing settings.
    5. When prompted to overwrite the newer version with the older one, confirm the operation.

At the end of the installation process, your site will be running the previous version of the plugin. You can keep running it like that, while we look into the issue you reported.

Any questions?

This is one of the longest articles we have ever published. We would like to thank you for staying with us and making it so far. 😄

If you have any questions for us. In that case, please feel free to reach out and we will get back to you as soon as possible. Thanks for reading, and for your continued support. Keep rocking! 👍

Diego Zanella – The Aelia Team