No Code Attached Yet bug
avatar redevorob
redevorob
8 Jul 2026

What happened?

Summary

A single article's own "Layout" selection (article_layout in #__content.attribs) is silently discarded and replaced with the site's global default Article layout, whenever the article is reached through a menu item (e.g. a "Single Article" menu item type). This happens unconditionally, in com_content's ArticleModel::getItem(), regardless of what the article's Layout field is actually set to in the article editor.

Environment

  • Joomla version: 6.1.2
  • PHP version: (fill in)
  • Affected file: components/com_content/src/Model/ArticleModel.php
  • Reproducible with an unmodified core install; no third-party plugins required to trigger it.

Steps to reproduce

  1. Create (or edit) an article. In the article's Layout tab, choose a specific alternate layout, e.g. select a template's blog layout (stored as article_layout: "<template>:blog" in the article's attribs).
  2. Confirm the site's Content → Options → Article global default Layout is set to something different, e.g. <template>:standard.
  3. Create a menu item of type Single Article pointing directly at that article, and do not set any layout override on the menu item itself (there is no such field — see below).
  4. Publish and visit the article via that menu item's URL.

Expected behavior

The article renders using the layout explicitly selected on the article itself (blog, in this example), as documented for the article "Layout" option and as the merge logic in Joomla\CMS\MVC\View\HtmlView::display() (called from Joomla\Component\Content\Site\View\Article\HtmlView::display()) is written to expect.

Actual behavior

The article renders using the site's global default Layout (standard) instead, ignoring the article's own selection entirely. This happens every time, not intermittently, for any article whose own layout differs from the global default and which is accessed via a matching menu item.

Root cause

In components/com_content/src/Model/ArticleModel.php, getItem() builds $data->params like this (abridged):

$registry = new Registry($data->attribs);

$data->params = clone $this->getState('params');   // seeded from menu/global state
$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 loop only pulls a param from the article's own attribs into $data->params when the menu item's resolved value for that key is literally the string 'use_article' ("Use Article Settings"). That sentinel is a real, selectable option for several display toggle fields (show_title, show_tags, link_titles, etc.) on the Blog/Featured/Archive listing menu item types — see e.g. components/com_content/tmpl/category/blog.xml.

However, article_layout is not one of those fields. It is defined only:

  • On the article's own edit form (administrator/components/com_content/forms/article.xml), as a componentlayout field with useglobal="true" — it has no use_article option.
  • Nowhere on the Single Article menu item type's own options (components/com_content/tmpl/article/default.xml defines no layout/article_layout field at all).

Because no UI ever lets article_layout take the value 'use_article', the if ($value === 'use_article') check can never be true for that key. $data->params->get('article_layout') therefore always returns whatever $this->getState('params') already resolved it to before this loop runs — which, for a Single Article menu item (which defines no layout field of its own), falls through to the global com_content Article Options default layout. The article's own attribs.article_layout value is read into $registry but never makes it into $data->params at all.

Downstream, Joomla\Component\Content\Site\View\Article\HtmlView::display() relies on exactly this value:

} elseif ($layout = $item->params->get('article_layout')) {
    // Check for alternative layout of article
    $this->setLayout($layout);
}

expecting it to reflect the article's own setting (it separately handles a menu-item-specific override via $active->query['layout'], which is the intended mechanism for a menu item to override the article — that path is unaffected by this bug and works correctly). Since the model already overwrote the value before the view ever sees it, this expectation is violated, and the article silently renders with the wrong layout.

Suggested fix

After the existing use_article merge loop in ArticleModel::getItem(), explicitly restore article_layout from the article's own registry when it has an explicit value, since no menu item type can ever legitimately claim it via the use_article mechanism:

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

// article_layout has no "Use Article Settings" (use_article) option on any menu item
// type, so it never qualifies for the use_article merge above and the article's own
// selection would otherwise be lost, silently falling back to the menu/global-derived
// value $data->params was cloned from.
if ($registry->get('article_layout') != '') {
    $data->params->set('article_layout', $registry->get('article_layout'));
}

$data->metadata = new Registry($data->metadata);

This was verified to resolve the issue locally: with the patch applied, an article with article_layout explicitly set to a non-default value renders with that layout as expected when accessed via a Single Article menu item, while global-default articles are unaffected.

Additional notes

  • This is easy to miss because it's only observable when an article's own layout selection differs from the site's global default Article layout — sites where most/all articles intentionally use the global default won't notice it.
  • Confirmed via runtime tracing that this is not a caching issue: the raw #__content.attribs row correctly contained the article's chosen layout, but ArticleModel::getItem()'s returned $data->params did not, even with all Joomla caching disabled.

Version

5.4

Expected result

No response

Actual result

No response

System Information

No response

Additional Comments

No response

avatar redevorob redevorob - open - 8 Jul 2026
avatar joomla-cms-bot joomla-cms-bot - change - 8 Jul 2026
Labels Added: No Code Attached Yet bug
avatar joomla-cms-bot joomla-cms-bot - labeled - 8 Jul 2026
avatar alikon alikon - change - 8 Jul 2026
Status New Closed
Closed_Date 0000-00-00 00:00:00 2026-07-08 16:42:11
Closed_By alikon
avatar alikon alikon - close - 8 Jul 2026
avatar alikon
alikon - comment - 8 Jul 2026

please test #48060

Add a Comment

Login with GitHub to post a comment