Deprecations and Preparing for Joomla 7

This content was generated with the assistance of AI and should be verified against the official Joomla documentation before being relied on in production.

This sub-section’s Joomla bibliography lists the reference material consulted while preparing these pages.

Joomla removes code slowly and announces it in advance. A method that is deprecated in one release keeps working for years, is then removed from the core in a later major version and, when possible, is kept alive for one more release cycle inside a compatibility plugin. This page explains that policy, walks through the official per-version migration notes from 5.4 to 7.0, lists what the 7.0 development branch already removes, describes the "Behaviour - Backward Compatibility 7" plugin, and summarises the product strategy for 7.x. Everything about 7.0 is a plan or a work in progress, not a released fact, and is marked as such. The example extension is the fictitious Tallpine Hiking Club package pkg_tallpine (component com_tallpine, namespace Tallpine\Component\Tallpine).

It was written against Joomla 6.2.x on PHP 8.3+ and checked on 2026-10-30. Joomla 6.2.0 was released on 2026-10-13 and is the current version; 5.x is in its security-only period (5.4.10 was the last bugfix release) and 4.x is end of life. The development branches 6.3-dev and 7.0-dev exist in the source repository, and the Manual already carries draft pages for 6.3 and for 6.4 to 7.0 that state they can change at any time.

The details of the individual APIs are covered elsewhere and are linked, not repeated: Error Handling and Legacy APIs explains setError(), the legacy J* class aliases, CMSObject and the Filesystem and Input packages, and Updating Joomla and Automated Core Updates explains how to run the update itself. The release schedule is on Versions, Release Cycle and Support.

The deprecation policy

Joomla follows semantic versioning as far as the life cycle of a CMS allows. The Manual’s section About Updates & Upgrades Documentation states the rules that matter for extension authors:

  • a deprecation is introduced in a minor release, not in a major one;

  • deprecated code has to remain available for as long as the Joomla version in which it was deprecated is still supported, so something deprecated in 4.x can be removed at the earliest in 6.0, and it does not have to be removed then (the Production Department motion PROD2022/011 set this rule);

  • removing code earlier than that needs a separate Production Department motion;

  • wherever possible, removed code is moved into a backward compatibility plugin, so that it can be used for one more release cycle.

The practical effect is that a third-party developer has at least two years between the first deprecation notice and the removal. The @deprecated tag in the source states both numbers, for example @deprecated 4.0 will be removed in 7.0 on CMSObject: the first number is the version that deprecated it, the second the version that is expected to remove it. The expected removal version can move. The Manual’s 5.3 to 5.4 notes list three cases where the removal was postponed from 6.0 to 7.0: the old event API (events without an event class), the old Editor and Captcha plugin APIs, and JLoader::register(). Always read the migration notes of the version you target instead of relying on an older tutorial.

The same policy explains the shape of the backward compatibility plugins:

Major Compatibility plugin Role

5.0

Behaviour - Backward Compatibility

Keeps Joomla 4 code running on 5. It has to be disabled before updating from 5.4 to 6.

6.0

Behaviour - Backward Compatibility 6 (BC6)

Installed and enabled in 5.4 (where it does nothing) so that the update to 6 can run old extensions. Installed but disabled on new 6.0 installations.

7.0 (development)

Behaviour - Backward Compatibility 7

Holds the code removed in 7.0 that can still be offered for one more cycle. Not released yet.

Both plugins belong to the behaviour plugin group because that group loads before every other plugin, which backward compatibility needs. The Manual warns developers not to create their own plugin in the behaviour group, because the group may be removed in a future release. The 5.4 to 6 procedure (disable the old plugin, enable BC6, switch the update channel) is in Upgrading Joomla 5 to 6.

A timeline from 5.4 to 7.0

flowchart LR A["5.4 (2025-10-14)<br/>BC6 plugin installed,<br/>removals postponed to 7.0"] --> B["6.0 (2025-10-14)<br/>CMSObject usage, CMS Input,<br/>Filesystem moved to BC6"] B --> C["6.1 (2026-04-14)<br/>nocache asset version,<br/>lazy plugin loading"] C --> D["6.2 (2026-10-13)<br/>modular build scripts,<br/>security flag on updates"] D --> E["6.3 (planned 2027-04)<br/>draft notes"] E --> F["6.4 and 7.0<br/>expected together in 2027<br/>BC7 plugin"]

The cycle is a major every two years, with four minors in between, and the last minor (x.4) is a bridge release without new features that is released together with the next major: 5.4.0 and 6.0.0 were both published on 2025-10-14. The roadmap page of the developer site lists dates only up to 6.3, and all its dates are tentative, so the dates for 6.4 and 7.0 follow from the cycle and are not announced.

The per-version migration notes

The Manual keeps the code-level notes separate from the version-specific development manual, because they are meant to be read across versions. Each pair of releases has a page with the same sub-pages: New features, New deprecations, Removed and Backward Incompatibility, and, where relevant, Compatibility Plugin. The advice is to read every page from the version your code was written for up to the version you want to support, because that also catches changes that older code never picked up.

Step What the notes cover

5.4 to 6.0

The large one. New deprecations (the Joomla\CMS\Http package, the input property of the application classes, CMSPlugin::registerListeners(), the $_db property and getDbo()/setDbo() on tables, the $app property of FieldsPlugin, the UCM system). Removals: CMSObject usage in core and the getItem() return type, the CMS Input object, JPATH_PLATFORM, the CMS BaseApplication and CLI classes, the CMS Filesystem package (moved to BC6), GMT replaced by UTC, $app removed from plugins as a template variable, the $db reference removed from views. A separate page, Error handling in Joomla 6.0 and onwards, covers setError().

6.0 to 6.1

New features: the string nocache as the version of an asset in joomla.asset.json, a grid layout and a new event for the subform field, and lazy loading of plugins on PHP 8.4 and later. The page lists no new deprecations.

6.1 to 6.2

New features: the modular build script system, which compiles or watches a single extension without a full rebuild. The page lists no new deprecations.

6.2 to 6.3

Draft page for the development branch. No new deprecations listed so far.

6.4 to 7.0

Draft pages for the development branch. They list the removals described in the next section, one new deprecation (finder plugin adapters must receive the database in their constructor) and the 7.0 compatibility plugin.

Two cautions apply to the notes themselves. First, the pages of the minor releases say that no deprecations were introduced "yet"; that text is written while a release is in development and is not always updated afterwards, so check the @deprecated tags of the source (or run a static analysis, see below) instead of treating an empty page as a guarantee. Second, the draft pages for versions that are not released can change at any time.

What 7.0 is expected to remove

The 6.4 to 7.0 page of the Manual, Removed and Backward Incompatibility, is the working list of the 7.0 development branch. It starts with a section on what moves into the compatibility plugin and then lists plain removals. The items that most affect extension code are summarised here. The list is still growing, so treat it as a preview.

Plugin properties $app and $db

Since the 4.x series, CMSPlugin filled the properties $app and $db of a plugin automatically when the class declared them. In 7.0 that detection is removed (it is the reason older plugins "just work" without any wiring). The same properties are removed from ActionLogPlugin ($app and $db), FieldsPlugin ($app) and PrivacyPlugin ($db). Finder plugins that extend the indexer Adapter class must now receive the database in their constructor.

A plugin that still reads $this->app or $this->db fails with a notice or an error on a null property in 7.0 unless the compatibility plugin or its own code fills them in. The fix is to inject the services in services/provider.php, which is also how every core plugin is written today:

<?php

\defined('_JEXEC') or die;

use Joomla\CMS\Extension\PluginInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\Database\DatabaseInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Tallpine\Plugin\Content\TallpineConditions\Extension\TallpineConditions;

return new class () implements ServiceProviderInterface {
    public function register(Container $container): void
    {
        $container->set(
            PluginInterface::class,
            function (Container $container) {
                $plugin = new TallpineConditions(
                    (array) PluginHelper::getPlugin('content', 'tallpine_conditions')
                );
                $plugin->setApplication(Factory::getApplication());
                $plugin->setDatabase($container->get(DatabaseInterface::class));

                return $plugin;
            }
        );
    }
};

The extension class then uses the accessors and the aware trait instead of the properties:

<?php

namespace Tallpine\Plugin\Content\TallpineConditions\Extension;

\defined('_JEXEC') or die;

use Joomla\CMS\Event\Content\ContentPrepareEvent;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Event\SubscriberInterface;

final class TallpineConditions extends CMSPlugin implements SubscriberInterface
{
    use DatabaseAwareTrait;

    public static function getSubscribedEvents(): array
    {
        return ['onContentPrepare' => 'onContentPrepare'];
    }

    public function onContentPrepare(ContentPrepareEvent $event): void
    {
        // Joomla 5 and 6 code often used $this->app and $this->db here.
        $app = $this->getApplication();
        $db  = $this->getDatabase();

        if (!$app->isClient('site')) {
            return;
        }

        $query = $db->createQuery()
            ->select($db->quoteName('closed'))
            ->from($db->quoteName('#__tallpine_trails'))
            ->where($db->quoteName('id') . ' = :id')
            ->bind(':id', $id, \Joomla\Database\ParameterType::INTEGER);
        // ... execute and decorate the article text
    }
}

If an extension cannot use the aware trait or the provider, the Manual’s fallback is to set the properties in the plugin’s own constructor from Factory::getApplication() and from the container entry for DatabaseInterface. Because getApplication() and getDatabase() exist already in 5.x and 6.x, the migration can be done now, without waiting for 7.0, and the same code runs on 5.4, 6.2 and 7.0. Core plugin classes are final, so third-party code extends the abstract plugin base classes and not the core plugins.

CMSObject and the legacy property methods

Joomla\CMS\Object\CMSObject (formerly JObject) is annotated as deprecated since 4.0 and as removed in 7.0, with stdClass or Joomla\Registry\Registry as the replacement. In 6.0 core stopped using it: AdminModel::getItem() returns a stdClass, so the get() and set() methods are no longer available on the result.

The 7.0 branch goes one step further and removes LegacyPropertyManagementTrait (the get(), set(), def(), getProperties() and setProperties() methods, which could read and write protected properties) from CategoryNode, Changelog, BaseModel, AbstractView, Table and User. The trait has been deprecated since 4.3. Note in particular that a model or view that called $this->set('option', ...) or $view->get('property') as a property access now has to use ordinary public properties, while the view’s get('Items') that calls getItems() on the model keeps working. The error-handling half of CMSObject, LegacyErrorHandlingTrait, is discussed below.

<?php

use Joomla\Utilities\ArrayHelper;

// Before (works on 5.4 and 6.x, removed on the 7.0 branch)
$title = $table->get('title');
$table->set('title', 'Lake Aurora loop');
$all   = $table->getProperties(1);
$name  = $user->get('name');

// After (works everywhere)
$title        = $table->title;
$table->title = 'Lake Aurora loop';
$all          = ArrayHelper::fromObject($table, false);
$name         = $user->name;

The filesystem shim

In 6.0 the CMS classes Joomla\CMS\Filesystem\File, Folder, Path, Stream and Patcher were moved out of the core library into BC6, with 7.0 as the announced removal. The replacement is the Joomla Framework package joomla/filesystem (namespace Joomla\Filesystem), which is already bundled with the core. On the 7.0 branch the compatibility plugin directory plugins/behaviour/compat7/classes/Filesystem holds the same classes again, so the shim survives one more cycle for extensions that still call them but is not part of the 7.0 core.

<?php

use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\Filesystem\Path;

// Tallpine GPX upload handler
$target = Path::clean(JPATH_ROOT . '/images/trails/' . File::makeSafe($name));

Folder::create(\dirname($target));
File::upload($tmpPath, $target);

The framework classes throw exceptions on failure instead of returning false with a warning, so a straight search-and-replace of the namespace is not enough: wrap the calls in try/catch where a failure is expected. The detailed comparison is in the Filesystem section of Error Handling and Legacy APIs.

Error handling: setError() in core

The error protocol is removed in stages: setUseExceptions() and shouldUseExceptions() arrived in 5.4, core is converted step by step during 6.x, 7.0 removes the calls to setError() and the checks of the exceptions flag from the core, and the LegacyErrorHandlingTrait itself is planned to go in 8.0. In the 7.0 source the trait and its methods carry @deprecated ... will be removed in 7.0 tags, and CMSObject, which uses the trait, is on the same schedule. What matters for com_tallpine is that it stops relying on a false return value plus getError() and calls setUseExceptions(true) on its models and tables. The full guidance, with examples, is on Error Handling and Legacy APIs and is not repeated here.

Other removals worth scanning for

The same page lists many smaller items. The ones extension code is most likely to hit:

Removed in the 7.0 branch Use instead

Factory::getConfig(), Factory::getSession(), Factory::getMailer(), User::get() (throw an exception when the compatibility plugin is off)

Factory::getApplication()->get('sitename'), the application’s session, the MailerFactoryInterface service and direct property access on the user

Static getXxx() methods of module helper classes such as ArticlesNewsHelper

Boot the module and call the instance helper: Factory::getApplication()->bootModule('mod_articles_news', 'site')->getHelper('ArticlesNewsHelper')

The CMS Crypt package (Joomla\CMS\Crypt)

The framework package Joomla\Crypt, plus hash_equals(), mb_strlen() and mb_substr()

getCfg(), loadSession(), the static purgeMessages() and getApiRouter() on application classes

get(), the messages model, the ApiRouter service

Legacy one-time-password code in com_users (getOtpConfig(), generateOteps() and similar)

Multi-factor authentication, which replaced it in 4.2

The PHPassHandler password hash handler

Users who have not logged in since Joomla 3.2.1 must reset their password

The form fields radiobasic, logcreator and Uploaddirs

radio with the layout joomla.form.field.radio.switcher, user and Folderlist

JavaScript Joomla.JText, Joomla.popupWindow and window.Calendar

Joomla.Text, a native window.open() call and JoomlaCalendar.init()

The generic onBeforeDelete and onAfterDelete events of nested tables

The typed table events

The Behaviour - Backward Compatibility 7 plugin

The 6.4 to 7.0 page of the Manual says that, in 7.0, the compatibility plugin of 6.0 is replaced by a new plugin called "Behaviour - Backward Compatibility 7". The development branch already contains it as plugins/behaviour/compat7 (extension name plg_behaviour_compat7, namespace Joomla\Plugin\Behaviour\Compat7, version 7.0.0). Its description says that, when enabled, it provides backward compatibility to the previous major version, Joomla 6, for extensions that do not follow the current coding standards. Because it is unreleased, its options and contents can change before 7.0.

What the branch shows today:

  • three yes/no options: Classes Aliases (aliases for renamed or namespaced classes, default off), Include Deprecated Classes (classes removed from the core but kept under the plugin’s classes folder, default on) and Removed Assets (empty placeholder entries in a removed.asset.json, so that a Web Asset Manager call for a removed asset does not raise an exception, default on);

  • the plugin directory contains the Filesystem classes, the CMS Input classes, the CMS BaseApplication, CliApplication and CLI helper classes, the CMS Crypt classes, the RadiobasicField form field and its layout;

  • the plugin defines the constant COMPAT_JOOMLA_7 when it is loaded. Selected functions (Factory::getConfig(), Factory::getSession(), Factory::getMailer(), User::get()) test for that constant and throw an exception when it is missing. That makes the missing plugin visible during testing instead of silently failing in production, and it lets a site owner see which old override or extension needs attention.

The consequence for a site is the same as with BC6: enabling the plugin buys one release cycle, not a permanent solution. An extension that needs it should be treated as an extension that needs maintenance.

Preparing pkg_tallpine for Joomla 7 today

Everything below works on Joomla 5.4 and 6.2, so the package can be prepared long before 7.0 appears:

  1. Update the development site to the latest 6.2.x and, if the package supports 5.4, keep a 5.4 test site as well.

  2. Switch off every compatibility plugin on a test site (BC6 on 6.x) and run the package through its tests. Whatever breaks relies on removed or compat-only code. Compare with the checklist in Error Handling and Legacy APIs.

  3. Search the code for the patterns above and fix them. The script below is a starting point; a result is a candidate, not a proof.

  4. Raise the minimum PHP version in the package manifest only when the target Joomla version requires it. Minimum requirements rise only in the first release of a major.

  5. Re-run the checks against the 7.0 development builds when they become available, and read the 6.4 to 7.0 notes again at that time, because the list will have changed.

#!/usr/bin/env bash
# Scan the Tallpine package for APIs that the 7.0 branch removes or moves to compat7.
set -eu
SRC="${1:-./pkg_tallpine}"

grep -rnE '\$this->(app|db)\b' "$SRC" --include='*.php' \
  && echo "-> use getApplication() / getDatabase() and inject in provider.php"
grep -rnE 'CMSObject|->setError\(|->getError\(|->getProperties\(' "$SRC" --include='*.php' \
  && echo "-> use exceptions and stdClass / ArrayHelper::fromObject()"
grep -rnE 'Joomla\\CMS\\(Filesystem|Input|Crypt)\\' "$SRC" --include='*.php' \
  && echo "-> use the joomla-framework packages"
grep -rnE 'Factory::get(Config|Session|Mailer)\(' "$SRC" --include='*.php' \
  && echo "-> use the application and the service container"
grep -rnE 'Joomla\.(JText|popupWindow)|window\.Calendar' "$SRC" --include='*.js' \
  && echo "-> use Joomla.Text, window.open and JoomlaCalendar"
true

Static analysis helps with the same job. PHPStan, with the Joomla stubs or the checked-out core on the autoload path, reports calls to methods that no longer exist, and the PHP deprecation tags of Joomla’s own classes are visible to IDEs. See Coding Standards and Static Analysis for the toolchain used across this sub-section, and Build and CI for Extensions for running the checks against several Joomla versions in a matrix.

Common errors and pitfalls

  • Enabling both compatibility plugins. BC and BC6 cannot be on together when updating from 5.4 to 6. After the update only BC6 is relevant. See Upgrading Joomla 5 to 6.

  • Shipping your own plugin in the behaviour group. The Manual says the group may be removed. Use system or the group that matches the event.

  • Trusting the pre-update check. The extension compatibility check is not a reliable source of truth; test on a copy.

  • Assuming a deprecated method is safe because it still works. Deprecated code is supported only until its removal version, and the removal version can be later than first announced, but it never moves earlier without a motion.

  • Relying on the compat plugin to ship. A site that needs a compatibility plugin to run is on borrowed time: the plugin lasts one major cycle.

  • Mixing protocols. Calling setError() in a new class and checking exceptions in the caller leaves failures unreported.

  • Documentation of the draft pages. The 6.3 and 6.4 to 7.0 pages are drafts; a link to them in a user guide can become stale.

Security notes

Deprecations are often security-motivated. The 7.0 branch removes the legacy password hash handler PHPassHandler (accounts that have not logged in since Joomla 3.2.1 will need a password reset) and the obsolete one-time-password code paths that had not worked since multi-factor authentication replaced them in 4.2. The CMS Crypt package gives way to the maintained framework package, and the URL form-field layout no longer escapes values itself, so an extension that renders joomla.form.field.url directly must escape the value. Staying on an unsupported release is the larger risk: security fixes for 5.x end on 2027-10-12, and the compatibility plugins cannot be used as a long-term security posture. Keep security patches current through automated core updates and plan the 7.0 move early.

The strategy for 7.x, stated as plans

The Joomla Product Strategy page of the developer site was created on 2025-09-08 from a three-day sprint (it is version 1.0.3, last modified on 2025-10-01, with a roadmap status of 2025-10-05) and says that all dates are tentative. It is built on three pillars: defend and expand the market position, increase efficiency (including readiness for AI), and simplify onboarding. It splits the work into a 6.x branch (2025 to 2027) and a "7.x and beyond" branch (2027 onwards).

Pillar 6.x (2025 to 2027) 7.x and beyond (2027+)

Defend and expand

WCAG 2.2 AA for the front end and the administrator; extended content versioning with draft states; a built-in proof-of-work captcha

A multi-site or sub-site concept; automated workflows; filtering items by custom field values; a framework-agnostic design system for templates; a rate limiting framework

Increase efficiency

Documentation for end users, developers and machine-readable web services; improved web services (refined endpoints, OAuth, a "headless only" mode); MCP servers; investigation of an AI framework

An "Ajaxified" administrator; a site-wide content language filter; a standardised horizontal component API for third-party developers; better default code for third-party developers

Simplify onboarding

A new sample data set; editor improvements for links and media; configurable authoring forms; intelligent module assignment; redirects for renamed, removed or unpublished items

A new default template with the goal of one new template per major version; user interface presets for user roles

Three of the 7.x themes matter for the Tallpine site:

  • Multisite. Joomla has no multisite support in core today; sites that need several sites use separate installations or third-party tools (see Multi-site Options and Scaling). The strategy lists a multi/subsite concept as a goal for 7.x. No design, version or date is published, so do not build a Tallpine regional-club network around it.

  • Design system. The framework-agnostic templates and design system, together with the goal of a new default template per major version, suggests that Cassiopeia may be replaced as the default in a future major. Child templates such as cassiopeia_tallpine should therefore keep their overrides small and their tokens (colours, fonts) in variables; see Child Templates.

  • Rate limiting. A rate limiting framework is listed under defend and expand for 7.x. Until it exists, throttling of the login form, the Web Services API and the contact form belongs on the reverse proxy or web application firewall; see Web Server, Reverse Proxy and HTTPS.

For the 6.x items that touch headless use and artificial intelligence, the plans are discussed in Headless Joomla and AI, MCP and the Roadmap. All of this is a strategy, not a commitment, and the roadmap shows only what has been accepted for each release.

Where older books and tutorials are outdated

  • Developing Extensions for Joomla! 5 (2023) shows plugins that read $this->db and $this->app as if they were permanent features, and models that return CMSObject instances. Both are removed or on the way out; use the Aware traits, getApplication() and getDatabase(), and stdClass.

  • Joomla! 4 Masterclass (2023) targets 4.x, which reached end of life in 2025-10, and does not cover the compatibility plugins or the 6.x migration notes at all.

  • Tutorials that say deprecated code is removed in the next major version describe the policy before the 2022 motion. Today the earliest removal is the second major after the deprecation.

  • Material that says the JPATH_PLATFORM guard, JFactory and JText are the normal way to write Joomla code predates the 6.0 removals. Use defined('_JEXEC') or die;, namespaced classes and Text.