Joomla Plugins & events changes: Joomla 3 → 4, 5 and 6
6 issues in this guide
Plugins stop loading when they still extend JPlugin or register through JDispatcher. This guide groups 6 entries: onContentPrepare / onAfterDispatch / …, function onContentPrepare(...), JDispatcher::getInstance(), JPlugin, JPluginHelper, plugins/content/foo/foo.xml with a single php file. The replacement pattern is CMSPlugin (or a dedicated subscriber class) implementing SubscriberInterface::getSubscribedEvents(), with PluginHelper for loading — all under Joomla\CMS\Plugin. Event method names stay familiar; the registration model does not. Manifest filename and folder layout for plugins also moved after Joomla 1.5-style discover installs. Hop mix: 1 at Joomla 3 → 4; 5 at Joomla 5 → 6. Disable the BC plugin on Joomla 5 to surface Class "JPlugin" / "JDispatcher" fatals, then convert each listener to a subscribed event map using the before/after blocks below. Body rewrites that once called JResponse::getBody() belong with document and Web Asset Manager approaches documented in the media-assets guide. Catalog replacements in this guide include onContentPrepare / onAfterDispatch / … → SubscriberInterface::getSubscribedEvents(); function onContentPrepare(...) → CMSPlugin + SubscriberInterface::getSubscribedEvents(); JDispatcher::getInstance() → Event dispatcher + SubscriberInterface; JPlugin → Joomla\CMS\Plugin\CMSPlugin. Open each h2 anchor for the full before/after, fix list, and error strings shipped in the reference data.
EVENT-LIST-001
onContentPrepare / onAfterDispatch / …
Core plugin event names (J3 methods → subscribers)
The event names still fire. The implementation must become a subscriber on native Joomla 6. Search this entry for any onContent*/onUser*/onAfter* method.
onContentPrepare / onAfterDispatch / … → SubscriberInterface::getSubscribedEvents()
Dies at Joomla 5 → 6Symptoms people search
onContentPrepare not firing · onAfterDispatch · onBeforeCompileHead · onUserLogin · onContentBeforeSave
Replace this code
Swap onContentPrepare / onAfterDispatch / … for SubscriberInterface::getSubscribedEvents().
Joomla 3
Remove or stop calling this
public function onAfterInitialise() {}
public function onAfterRoute() {}
public function onAfterDispatch() {}
public function onBeforeCompileHead() {}
public function onContentPrepare($ctx, &$article, &$params, $page=0) {}
public function onContentAfterTitle(...) {}
public function onContentBeforeDisplay(...) {}
public function onContentAfterDisplay(...) {}
public function onContentPrepareForm($form, $data) {}
public function onContentBeforeSave(...) {}
public function onContentAfterSave(...) {}
public function onContentBeforeDelete(...) {}
public function onContentChangeState(...) {}
public function onUserLogin(...) {}
public function onUserLogout(...) {}
public function onUserAfterSave(...) {}
public function onExtensionAfterInstall(...) {}
public function onDisplay(...) {}Joomla 4 / 6
Use this instead
Map each name in getSubscribedEvents() to a method that receives a typed Event. Do not take &$article by reference.How to fix it
- 1Implement SubscriberInterface.
- 2Register every event you handled as a J3 method.
- 3Read arguments from the Event object.
Also known as
onAfterInitialise · onAfterRoute · onAfterDispatch · onBeforeCompileHead · onAfterRender · onContentPrepare · onContentAfterTitle · onContentBeforeDisplay · onContentAfterDisplay · onContentPrepareForm · onContentBeforeSave · onContentAfterSave · onContentBeforeDelete · onContentChangeState · onUserLogin · onUserLogout · onUserAfterSave · onExtensionAfterInstall · onDisplay
There is no 1:1 swap for this one. The architecture changed. If you cannot rewrite it, Infyways can.
EVENT-SUBSCRIBER-001
function onContentPrepare(...)
JPlugin onX methods vs SubscriberInterface
Method-name events still fire, but Joomla 4+ wants subscribers with typed Event objects. Native Joomla 6 quality means SubscriberInterface, not a JPlugin with onContentPrepare by convention.
function onContentPrepare(...) → CMSPlugin + SubscriberInterface::getSubscribedEvents()
Dies at Joomla 5 → 6Symptoms people search
plugin does not run on Joomla 6 · onContentPrepare never called
Replace this code
Swap function onContentPrepare(...) for CMSPlugin + SubscriberInterface::getSubscribedEvents().
Joomla 3
Remove or stop calling this
class PlgContentLms extends JPlugin {
public function onContentPrepare($context, &$article, &$params, $page = 0) {}
}Joomla 4 / 6
Use this instead
class Lms extends CMSPlugin implements SubscriberInterface {
public static function getSubscribedEvents(): array {
return ['onContentPrepare' => 'prepare'];
}
public function prepare(Event $event): void {}
}How to fix it
- 1Extend CMSPlugin and implement SubscriberInterface.
- 2Map event names in getSubscribedEvents().
- 3Read arguments from the Event object, not &$article by reference.
Also known as
SubscriberInterface · onContentPrepare · onAfterRender · JPlugin
There is no 1:1 swap for this one. The architecture changed. If you cannot rewrite it, Infyways can.
JDISPATCHER-CLASS-001
JDispatcher::getInstance()
JDispatcher / JEventDispatcher
The old dispatcher was removed in Joomla 4. Plugins should subscribe to events, not trigger JDispatcher.
JDispatcher::getInstance() → Event dispatcher + SubscriberInterface
Dies at Joomla 3 → 4What you will see
- Class "JDispatcher" not found
- Class "JEventDispatcher" not found
Symptoms people search
plugin events never fire · trigger() fatal
Replace this code
Swap JDispatcher::getInstance() for Event dispatcher + SubscriberInterface.
Joomla 3
Remove or stop calling this
$dispatcher = JDispatcher::getInstance();
$dispatcher->trigger('onFoo', $args);Joomla 4 / 6
Use this instead
$dispatcher = Factory::getApplication()->getDispatcher();
// Plugins should implement SubscriberInterfaceHow to fix it
- 1Stop calling JDispatcher::getInstance().
- 2For plugins, implement SubscriberInterface::getSubscribedEvents().
- 3To dispatch, use the application dispatcher and Event classes.
Also known as
JDispatcher · JEventDispatcher · trigger(
There is no 1:1 swap for this one. The architecture changed. If you cannot rewrite it, Infyways can.
JPLUGIN-CLASS-001
JPlugin
JPlugin class name
JPlugin is a Joomla 3 global class. Joomla 4 still has an alias. Joomla 5 needs the Behaviour – Backward Compatibility plugin. Native Joomla 6 does not load that alias — you get Class "JPlugin" not found.
JPlugin → Joomla\CMS\Plugin\CMSPlugin
Dies at Joomla 5 → 6What you will see
- Class "JPlugin" not found
- Class 'JPlugin' not found
- Failed to open stream: JPlugin
Symptoms people search
white screen after disabling compatibility plugin · class not found on Joomla 6 · works on Joomla 5 until I turn off backward compatibility · plugin not loading
Replace this code
Swap JPlugin for Joomla\CMS\Plugin\CMSPlugin.
Joomla 3
Remove or stop calling this
JPlugin::getInstance();
// or new JPlugin()Joomla 4 / 6
Use this instead
use Joomla\CMS\Plugin\CMSPlugin;
// Call the namespaced class. Do not keep the J prefix.How to fix it
- 1Add a use statement for Joomla\CMS\Plugin\CMSPlugin.
- 2Replace every JPlugin with the short class name from that use line.
- 3Disable Behaviour – Backward Compatibility on a Joomla 5 staging site. If it fatals, this class is still in the code.
Also known as
JPlugin · Joomla\CMS\Plugin\CMSPlugin · class alias · J prefix
JPLUGINHELPER-CLASS-001
JPluginHelper
JPluginHelper class name
JPluginHelper is a Joomla 3 global class. Joomla 4 still has an alias. Joomla 5 needs the Behaviour – Backward Compatibility plugin. Native Joomla 6 does not load that alias — you get Class "JPluginHelper" not found.
JPluginHelper → Joomla\CMS\Plugin\PluginHelper
Dies at Joomla 5 → 6What you will see
- Class "JPluginHelper" not found
- Class 'JPluginHelper' not found
- Failed to open stream: JPluginHelper
Symptoms people search
white screen after disabling compatibility plugin · class not found on Joomla 6 · works on Joomla 5 until I turn off backward compatibility
Replace this code
Swap JPluginHelper for Joomla\CMS\Plugin\PluginHelper.
Joomla 3
Remove or stop calling this
JPluginHelper::getInstance();
// or new JPluginHelper()Joomla 4 / 6
Use this instead
use Joomla\CMS\Plugin\PluginHelper;
// Call the namespaced class. Do not keep the J prefix.How to fix it
- 1Add a use statement for Joomla\CMS\Plugin\PluginHelper.
- 2Replace every JPluginHelper with the short class name from that use line.
- 3Disable Behaviour – Backward Compatibility on a Joomla 5 staging site. If it fatals, this class is still in the code.
Also known as
JPluginHelper · Joomla\CMS\Plugin\PluginHelper · class alias · J prefix
PLUGIN-XML-FILENAME-001
plugins/content/foo/foo.xml with a single php file
Plugin XML: only <filename plugin="x">x.php</filename>
A single php file still installs. Native Joomla 4+ plugins use a service provider and a subscriber class. The J3 file will run as CMSPlugin until you rewrite events.
plugins/content/foo/foo.xml with a single php file → Namespaced plugin class + services/provider.php
Dies at Joomla 5 → 6Symptoms people search
plugin installs but events never fire on J6 · no provider.php
Replace this code
Swap plugins/content/foo/foo.xml with a single php file for Namespaced plugin class + services/provider.php.
Joomla 3
Remove or stop calling this
<files>
<filename plugin="lms">lms.php</filename>
</files>Joomla 4 / 6
Use this instead
<namespace path="src">Acme\Plugin\Content\Lms</namespace>
<files>
<folder plugin="lms">services</folder>
<folder>src</folder>
</files>How to fix it
- 1Add services/provider.php.
- 2Move the plugin class into src/ and implement SubscriberInterface.
Also known as
filename plugin · plugin xml · services/provider.php
There is no 1:1 swap for this one. The architecture changed. If you cannot rewrite it, Infyways can.