No Code Attached Yet bug
avatar jcmelean
jcmelean
26 Jul 2026

What happened?

Steps to reproduce the issue

  1. In a com_content Article, open the Advanced Options tab and set Layout to any alternate layout that exists as a template override (e.g. Home:mylayout, stored internally as mylayout in the article_layout key of the article's attribs).
  2. Publish the article inside a Category, and reach it through a Category Blog / Category List menu item (i.e. NOT through a "Single Article" menu item that points directly at this article).
  3. Open the article on the front end.

Version

5.4

Expected result

The article renders using the alternate layout selected in Layout on the article itself (components/com_content/tmpl/article/mylayout.php or its template override), exactly as it did before upgrading to 5.4.x.

Actual result

The article silently falls back to default.php. No PHP notice, warning or exception is raised — HtmlView::loadTemplate() just resolves default.php because getLayout() never returns anything other than default.

The per-article Layout override (Advanced Options tab) only keeps working when the article is opened through a "Single Article" menu item whose own menu-level layout query var matches — i.e. exactly the one case where the article's own article_layout param isn't actually needed, because the menu item alternate layout mechanism handles it independently (components/com_content/src/View/Article/HtmlView.php, isset($active->query['layout']) branch).

System Information

  • Joomla! version: regression appears between 5.3.1 and 5.4.7 (confirmed via diff of a tracked, version-controlled install upgraded in place from 5.3.1 to 5.4.7 — see root cause below)
  • PHP version: 8.4
  • Any 3rd Party extensions: none required to reproduce; core com_content only

Additional Comments

Root cause

Joomla\Component\Content\Site\Model\ArticleModel::getItem() builds $data->params for the single-article view. In 5.3.1 this was:

// Convert parameter fields to objects.
$registry = new Registry($data->attribs);

$data->params = clone $this->getState('params');
$data->params->merge($registry);

The full article attribs registry (which includes article_layout) is unconditionally merged into $data->params.

In 5.4.7, presumably as part of the "use global / use article" per-field options work, this was changed to:

// Convert parameter fields to objects.
$registry = new Registry($data->attribs);

$data->params = clone $this->getState('params');
$globalParams = ComponentHelper::getParams('com_content', true);

$menuParamsArray = $this->getState('params')->toArray();
$articleArray    = [];

foreach ($menuParamsArray as $key => $value) {
    if ($value === 'use_article') {
        if ($registry->get($key) != '') {
            // Article has an explicit value, use it
            $articleArray[$key] = $registry->get($key);
        } else {
            // Article is "Use Global", fall back to global component param
            $articleArray[$key] = $globalParams->get($key);
        }
    }
}

if (\count($articleArray)) {
    $data->params->merge(new Registry($articleArray));
}

The wholesale $data->params->merge($registry) call was dropped. Now $data->params only ever receives keys from the article's own attribs when the corresponding menu/category param for that same key is literally the sentinel string 'use_article'. article_layout is not one of the fields that participates in that "use global/use article" selector — it's a standalone layout override — so it is never copied over anymore, no matter what the article itself has set. Every other value on $data->params ends up being whatever the active menu/category state already had, i.e. the article's own explicit settings for anything not modeled by the "use_article" convention are lost.

components/com_content/src/View/Article/HtmlView.php then reads $item->params->get('article_layout') to call setLayout(), and now always gets an empty value in this scenario, so the layout resolution in Joomla\CMS\MVC\View\HtmlView::loadTemplate() falls back to default silently (by design, via the "alternate layout can't be found, fall back to default layout" branch — except here it's not even "can't be found", the layout name was never set to begin with).

Suggested fix

Restore the full registry merge before applying the use_article overrides, so article-level params still win as a baseline and the use_article loop only handles the specific opt-in/opt-out fields it was designed for:

$data->params = clone $this->getState('params');
$data->params->merge($registry);   // <-- restore this line
$globalParams = ComponentHelper::getParams('com_content', true);

$menuParamsArray = $this->getState('params')->toArray();
$articleArray    = [];

foreach ($menuParamsArray as $key => $value) {
    if ($value === 'use_article') {
        if ($registry->get($key) != '') {
            $articleArray[$key] = $registry->get($key);
        } else {
            $articleArray[$key] = $globalParams->get($key);
        }
    }
}

if (\count($articleArray)) {
    $data->params->merge(new Registry($articleArray));
}

This keeps the new "use global / use article" behaviour intact for the fields it targets, while no longer discarding every other article-level param (most visibly article_layout, but potentially other custom-field-driven values too) that used to survive in 5.3.x.

I can open a PR with this change plus a regression test if that's useful — happy to follow whatever contribution process is preferred.

avatar jcmelean jcmelean - open - 26 Jul 2026
avatar joomla-cms-bot joomla-cms-bot - change - 26 Jul 2026
Labels Added: No Code Attached Yet bug
avatar joomla-cms-bot joomla-cms-bot - labeled - 26 Jul 2026
avatar joomdonation joomdonation - change - 26 Jul 2026
Status New Closed
Closed_Date 0000-00-00 00:00:00 2026-07-26 13:46:38
Closed_By joomdonation
avatar joomdonation joomdonation - close - 26 Jul 2026
avatar joomdonation
joomdonation - comment - 26 Jul 2026

Thanks for reporting @jcmelean . The issue was fixed by this PR #48060 and will be available in the next release 5.4.8. You can apply the change from that PR to your site now or wait for next release.

Add a Comment

Login with GitHub to post a comment