Joomla Media, assets & Web Asset Manager changes: Joomla 3 → 4, 5 and 6

8 issues in this guide

Assets are no longer a pile of $doc->addScript calls. This guide groups 8 entries: $doc->addScript(), $doc->addScriptDeclaration(), onAfterRender() { $body = JResponse::getBody(); }, JHelperMedia, JHtml::_('behavior.caption') internals, JImage, images/lms/hero.jpg (raw path), templateDetails.xml only. The replacement pattern is declare named assets in media/.../joomla.asset.json, register and use them through WebAssetManager (including inline script/style helpers), and resolve media field values with HTMLHelper::cleanImageURL() or MediaHelper::getCleanMediaFieldValue(). Templates that only ship templateDetails.xml need an asset JSON and WAM registration in index.php. Prefer public HTMLHelper / WAM APIs over scraping non-public JHtml internals. Hop mix: 3 at Joomla 3 → 4; 3 at Joomla 4 → 5; 2 at Joomla 5 → 6. Fixing this group early prevents CSS/JS ordering bugs after you move to Cassiopeia or a child template. Each anchor below repeats the catalog before/after for that exact call. Catalog replacements in this guide include $doc->addScript() → WebAssetManager + joomla.asset.json; $doc->addScriptDeclaration() → WebAssetManager addInlineScript / addInlineStyle; onAfterRender() { $body = JResponse::getBody(); } → Document events / WebAssetManager; JHelperMedia → Joomla\CMS\Helper\MediaHelper. Open each h2 anchor for the full before/after, fix list, and error strings shipped in the reference data.

ASSET-ADDSCRIPT-001

$doc->addScript()

addScript() / addStyleSheet() vs WebAssetManager

addScript/addStyleSheet still exist but they skip dependency order, versioning, and WebAssetManager. Joomla 4+ templates and extensions should declare assets in joomla.asset.json.

$doc->addScript() → WebAssetManager + joomla.asset.json

Dies at Joomla 4 → 5
Dies at Joomla 4 → 5J3: Works nativelyJ4: Deprecated — do not shipJ6: Deprecated — do not shipBC plugin: not applicablePatch possible — review itJavaScript

Symptoms people search

scripts load in the wrong order · jquery not defined because it loaded after my file · css missing after upgrade

Replace this code

Swap $doc->addScript() for WebAssetManager + joomla.asset.json.

Joomla 3

Remove or stop calling this

$doc = JFactory::getDocument();
$doc->addScript(JUri::root() . 'media/com_lms/js/lms.js');
$doc->addStyleSheet(JUri::root() . 'media/com_lms/css/lms.css');

Joomla 4 / 6

Use this instead

$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
$wa->useStyle('com_lms.lms')->useScript('com_lms.lms');
// Register those names in media/com_lms/joomla.asset.json

How to fix it

  1. 1Add media/.../joomla.asset.json with named assets.
  2. 2Replace addScript/addStyleSheet with $wa->useScript / useStyle.
  3. 3Move inline JS to addInlineScript via WAM.

Also known as

addScript · addStyleSheet · WebAssetManager · joomla.asset.json · WAM

ASSET-ADDSCRIPT-DECLARATION-001

$doc->addScriptDeclaration()

addScriptDeclaration / addStyleDeclaration

Declarations still work on Document but they skip asset ordering. WAM inline APIs are the Joomla 4+ path.

$doc->addScriptDeclaration() → WebAssetManager addInlineScript / addInlineStyle

Dies at Joomla 4 → 5
Dies at Joomla 4 → 5J3: Works nativelyJ4: Deprecated — do not shipJ6: Deprecated — do not shipBC plugin: not applicablePatch possible — review itJavaScript

Symptoms people search

inline js before jquery · addScriptDeclaration

Replace this code

Swap $doc->addScriptDeclaration() for WebAssetManager addInlineScript / addInlineStyle.

Joomla 3

Remove or stop calling this

$doc->addScriptDeclaration('alert(1);');
$doc->addStyleDeclaration('h1{color:red}');

Joomla 4 / 6

Use this instead

$wa->addInlineScript('alert(1);');
$wa->addInlineStyle('h1{color:red}');

How to fix it

  1. 1Move inline JS/CSS to WAM.
  2. 2Prefer a file in joomla.asset.json for anything reused.

Also known as

addScriptDeclaration · addStyleDeclaration · addInlineScript

EVENT-AFTERRENDER-001

onAfterRender() { $body = JResponse::getBody(); }

onAfterRender HTML string hacks

JResponse body swapping is Joomla 3. Joomla 4+ will surprise you with compressed output and split assets.

onAfterRender() { $body = JResponse::getBody(); } → Document events / WebAssetManager

Dies at Joomla 3 → 4
Dies at Joomla 3 → 4J3: Works nativelyJ4: Changed behaviourJ6: Changed behaviourBC plugin: no — already dead on J4Architecture change — no auto-fixEvents / plugins

What you will see

  • Class "JResponse" not found

Symptoms people search

script inject plugin broken · onAfterRender · JResponse

Replace this code

Swap onAfterRender() { $body = JResponse::getBody(); } for Document events / WebAssetManager.

Joomla 3

Remove or stop calling this

public function onAfterRender() {
    $body = JResponse::getBody();
    $body = str_replace('</body>', $js . '</body>', $body);
    JResponse::setBody($body);
}

Joomla 4 / 6

Use this instead

Add scripts with WAM. If you must mutate HTML, use the document after render APIs — JResponse is gone.

How to fix it

  1. 1Prefer WebAssetManager.
  2. 2If you still str_replace HTML, test with gzip on.

Also known as

JResponse · onAfterRender · setBody · getBody

There is no 1:1 swap for this one. The architecture changed. If you cannot rewrite it, Infyways can.

JHELPERMEDIA-CLASS-001

JHelperMedia

JHelperMedia class name

JHelperMedia 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 "JHelperMedia" not found.

JHelperMedia → Joomla\CMS\Helper\MediaHelper

Dies at Joomla 5 → 6
Dies at Joomla 5 → 6J3: Works nativelyJ4: Alias (old name still resolves)J6: Removed — fatalBC plugin: covers the class nameMechanical renameJoomla API

What you will see

  • Class "JHelperMedia" not found
  • Class 'JHelperMedia' not found
  • Failed to open stream: JHelperMedia

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 JHelperMedia for Joomla\CMS\Helper\MediaHelper.

Joomla 3

Remove or stop calling this

JHelperMedia::getInstance();
// or new JHelperMedia()

Joomla 4 / 6

Use this instead

use Joomla\CMS\Helper\MediaHelper;

// Call the namespaced class. Do not keep the J prefix.

How to fix it

  1. 1Add a use statement for Joomla\CMS\Helper\MediaHelper.
  2. 2Replace every JHelperMedia with the short class name from that use line.
  3. 3Disable Behaviour – Backward Compatibility on a Joomla 5 staging site. If it fatals, this class is still in the code.

Also known as

JHelperMedia · Joomla\CMS\Helper\MediaHelper · class alias · J prefix

JHTML-NONPUBLIC-001

JHtml::_('behavior.caption') internals

JHtml::_() calling a non-public helper

Joomla 4 made many JHtml helper methods non-public. Calls that worked as undocumented internals fatal with visibility errors.

JHtml::_('behavior.caption') internals → Public HTMLHelper methods / WebAssetManager only

Dies at Joomla 3 → 4
Dies at Joomla 3 → 4J3: Works nativelyJ4: Removed — fatalJ6: Removed — fatalBC plugin: no — already dead on J4You rewrite thisJoomla API

What you will see

  • Call to protected method
  • Call to private method
  • Call to undefined method

Symptoms people search

html helper protected · behavior helper fatal

Replace this code

Swap JHtml::_('behavior.caption') internals for Public HTMLHelper methods / WebAssetManager only.

Joomla 3

Remove or stop calling this

JHtml::_('behavior.caption');
JHtml::_('somehelper._hiddenMethod');

Joomla 4 / 6

Use this instead

// Only call documented public helpers.
HTMLHelper::_('calendar', $value, $name, $id);

How to fix it

  1. 1If the helper is not in the Joomla 4 HTMLHelper docs, stop calling it.
  2. 2Load the equivalent as a WAM asset.

Also known as

JHtml::_ non-public · protected helper

JIMAGE-CLASS-001

JImage

JImage class name

JImage 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 "JImage" not found.

JImage → Joomla\CMS\Image\Image

Dies at Joomla 5 → 6
Dies at Joomla 5 → 6J3: Works nativelyJ4: Alias (old name still resolves)J6: Removed — fatalBC plugin: covers the class nameMechanical renameJoomla API

What you will see

  • Class "JImage" not found
  • Class 'JImage' not found
  • Failed to open stream: JImage

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 JImage for Joomla\CMS\Image\Image.

Joomla 3

Remove or stop calling this

JImage::getInstance();
// or new JImage()

Joomla 4 / 6

Use this instead

use Joomla\CMS\Image\Image;

// Call the namespaced class. Do not keep the J prefix.

How to fix it

  1. 1Add a use statement for Joomla\CMS\Image\Image.
  2. 2Replace every JImage with the short class name from that use line.
  3. 3Disable Behaviour – Backward Compatibility on a Joomla 5 staging site. If it fatals, this class is still in the code.

Also known as

JImage · Joomla\CMS\Image\Image · class alias · J prefix

MEDIA-JOOMLAIMAGE-001

images/lms/hero.jpg (raw path)

Media field #joomlaImage:// paths

Joomla 4 media fields store #joomlaImage://local-0/images/foo.jpg?width=… not a plain path. Echoing the raw value breaks <img>.

images/lms/hero.jpg (raw path) → HTMLHelper::cleanImageURL() / MediaHelper::getCleanMediaFieldValue()

Dies at Joomla 3 → 4
Dies at Joomla 3 → 4J3: Works nativelyJ4: Changed behaviourJ6: Changed behaviourBC plugin: not applicablePatch possible — review itJoomla API

Symptoms people search

broken images after Joomla 4 · joomlaImage in src · media field

Replace this code

Swap images/lms/hero.jpg (raw path) for HTMLHelper::cleanImageURL() / MediaHelper::getCleanMediaFieldValue().

Joomla 3

Remove or stop calling this

echo '<img src="' . $this->item->image . '">';

Joomla 4 / 6

Use this instead

$img = HTMLHelper::cleanImageURL($this->item->image);
echo '<img src="' . htmlspecialchars($img->url) . '">';

How to fix it

  1. 1Run cleanImageURL before output.
  2. 2Or MediaHelper::getCleanMediaFieldValue().

Also known as

#joomlaImage · cleanImageURL · media field

TPL-NO-ASSET-JSON-001

templateDetails.xml only

Template without joomla.asset.json

Joomla 3 templates loaded CSS/JS with JHtml helpers. Joomla 4+ templates declare a web asset file. Without it, scripts collide or never load on Joomla 6.

templateDetails.xml only → joomla.asset.json + WebAssetManager in index.php

Dies at Joomla 4 → 5
Dies at Joomla 4 → 5J3: Works nativelyJ4: Changed behaviourJ6: Changed behaviourBC plugin: not applicableYou rewrite thisTemplates

Symptoms people search

template css not loading · scripts duplicated · no joomla.asset.json

Replace this code

Swap templateDetails.xml only for joomla.asset.json + WebAssetManager in index.php.

Joomla 3

Remove or stop calling this

JHtml::_('bootstrap.framework');
JHtml::_('jquery.framework');

Joomla 4 / 6

Use this instead

$wa = $this->getWebAssetManager();
$wa->useStyle('template.cassiopeia.user');
// Register template assets in joomla.asset.json

How to fix it

  1. 1Add joomla.asset.json next to templateDetails.xml.
  2. 2Load CSS/JS through WebAssetManager in index.php.
  3. 3Stop calling bootstrap.framework and jquery.framework in the template chrome.

Also known as

joomla.asset.json · templateDetails.xml · WebAssetManager

Start a project

Have something
to build?

Tell us what you are building. You will hear back from an engineer within one business day.

hello@infyways.com · Remote, working across time zones

Tell us about your project

Fill out the quick form and we'll reach out.