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 → 5Symptoms 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.jsonHow to fix it
- 1Add media/.../joomla.asset.json with named assets.
- 2Replace addScript/addStyleSheet with $wa->useScript / useStyle.
- 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 → 5Symptoms 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
- 1Move inline JS/CSS to WAM.
- 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 → 4What 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
- 1Prefer WebAssetManager.
- 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 → 6What 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
- 1Add a use statement for Joomla\CMS\Helper\MediaHelper.
- 2Replace every JHelperMedia 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
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 → 4What 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
- 1If the helper is not in the Joomla 4 HTMLHelper docs, stop calling it.
- 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 → 6What 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
- 1Add a use statement for Joomla\CMS\Image\Image.
- 2Replace every JImage 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
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 → 4Symptoms 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
- 1Run cleanImageURL before output.
- 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 → 5Symptoms 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.jsonHow to fix it
- 1Add joomla.asset.json next to templateDetails.xml.
- 2Load CSS/JS through WebAssetManager in index.php.
- 3Stop calling bootstrap.framework and jquery.framework in the template chrome.
Also known as
joomla.asset.json · templateDetails.xml · WebAssetManager