Indhold
- Sådan tilpasser du Joomla administrator template uden at ændre core
- Når Joomlas standardopsætning ikke matcher workflowet
- Hvor feltet kommer fra i Joomla 6
- Den rigtige løsning er ikke nødvendigvis den hurtigste
- Sådan blev feltet flyttet uden at ændre Joomla core
- Koden forklaret trin for trin
- Indsæt feltet sammen med metadata
- Du kan få koden jeg har brugt til den nye edit.php her:
- Små backend-forbedringer gør større forskel end mange tror
- Joomla backend er fleksibel
- Et lille override med stor praktisk effekt
Sådan tilpasser du Joomla administrator template uden at ændre core
Når man arbejder professionelt med Joomla, opdager man ret hurtigt, at der er småting, der kunne være bedre i workflowet, når der oprettes og optimeres nye artikler.
Joomla er ekstremt fleksibelt, men nogle dele af brugeroplevelsen i backend er stadig præget af historiske beslutninger, hvor funktionalitet har haft højere prioritet end workflow. Det betyder, at felter og indstillinger teknisk set ligger de rigtige steder – men ikke nødvendigvis de mest logiske steder.
Et godt eksempel er feltet Browser Page Title i artikelredigeringen.
Problemet
Browser Page Title bruges aktivt i SEO-arbejde, men ligger som standard gemt under Options/Indstillinger langt væk fra de øvrige metadatafelter.
Målet
Feltet skal flyttes visuelt tættere på Meta Description, så SEO-felterne bliver samlet og lettere at udfylde konsekvent.
Løsningen
Vi laver et update-sikkert administrator template override i Atum i stedet for at ændre direkte i Joomla core.
Når Joomlas standardopsætning ikke matcher workflowet
I mange CMS’er accepterer man bare den måde, backend er bygget på. Men en af Joomlas store styrker har altid været, at systemet kan tilpasses uden nødvendigvis at hacke sig ind i kernen.
For der er stor forskel på at lave en hurtig ændring direkte i core-filerne og på at lave en løsning, der er update-sikker og kan vedligeholdes over tid.
I dette tilfælde var målet egentlig ret simpelt: Browser Page Title skulle flyttes visuelt tættere på Meta Description, så alle SEO-relaterede felter stod samlet i artikelredigeringen.
Det giver et bedre workflow og fjerner unødvendige kliks.
Hvor feltet kommer fra i Joomla 6
Når man undersøger, hvordan artikelredigeringen er bygget op i Joomla 6, finder man hurtigt ud af, at feltet ikke er et klassisk metadatafelt.
Det ligger i artiklens XML-formular:
administrator/components/com_content/forms/article.xml
Selve feltet hedder:
article_page_title
og er placeret under gruppen:
attribs
Det er vigtigt at forstå, fordi det forklarer, hvorfor feltet ikke bare kan flyttes direkte over i metadata-sektionen.
Selvom det visuelt giver mening, er feltet teknisk set gemt som en artikelparameter. Hvis man blot flytter XML-definitionen rundt, risikerer man at ændre på dataflowet, field group-logikken eller den måde Joomla håndterer submit-processen på.
Det ville være en dårlig løsning.
Den rigtige løsning er ikke nødvendigvis den hurtigste
Den hurtigste løsning havde været at ændre Joomla core direkte. Men det er også den dårligste løsning. Som i: det skal du aldrig gøre.
Så snart Joomla bliver opdateret, vil ændringerne enten forsvinde eller skabe konflikter. I professionelle projekter skal man altid undgå at ændre direkte i core-filerne.
I stedet blev løsningen bygget som et administrator template override i Atum. Det er enkelt at lave, og vigtigst af alt: Joomla kan stadig bruge sin originale logik og originale formular, mens visningen af backend-layoutet bliver ændret.
Sådan blev feltet flyttet uden at ændre Joomla core
Udgangspunktet var Joomlas standardlayout til artikelredigering:
administrator/components/com_content/tmpl/article/edit.phpI stedet for at ændre direkte i Joomla core blev edit.php kopieret til et administrator override i Atum-template’et:
administrator/templates/atum/html/com_content/article/edit.phpDet betyder, at Joomla stadig bruger sine originale filer og funktioner, men at administrator-layoutet nu kan tilpasses uden at påvirke fremtidige opdateringer.
Hvis du ikke vil oprette filen manuelt kan du:
Opret override fra backend
Hvis du ikke ønsker at kopiere filerne manuelt, kan override’et oprettes direkte fra Joomla administratoren.
I Joomla admin
Gå til System → Administrator Templates → Atum → Detaljer og filer → Opret tilsidesætning.
Opret tilsidesætning
Under tilsidesætning vælger du com_content og derefter article. Joomla opretter herefter override-filen det rigtige sted.
Det smarte ved løsningen er, at Browser Page Title-feltet ikke bliver ændret teknisk. Joomla gemmer og behandler stadig feltet præcis som normalt. Det eneste, der ændres, er placeringen i backend.
For at kunne flytte feltet bliver det først “hentet ud” af formularen og gemt midlertidigt. Man kan tænke på det som at tage et element ud af sin normale placering, så det senere kan vises et andet sted i layoutet.
Koden forklaret trin for trin
Først gemmes informationen om, hvorvidt publiceringsindstillingerne skal vises.
$showPublishingOptions = $params->;get('show_publishing_options', 1);Her spørger koden Joomla: “Skal fanen eller området med publiceringsindstillinger vises?” Hvis Joomla ikke finder en specifik indstilling, bruges 1 som standard. I praksis betyder 1, at det er slået til.
Variablen $showPublishingOptions bliver altså en lille huskeseddel, som senere bruges til at afgøre, om feltet overhovedet skal flyttes.
$browserPageTitleField = '';Her oprettes en tom variabel. Den fungerer som en midlertidig plads, hvor feltet Browser Page Title senere kan gemmes.
Grunden til, at den starter tom, er sikkerhed: hvis feltet ikke skal flyttes, findes variablen stadig, men indeholder bare ingenting.
if ($showArticleOptions && $showPublishingOptions == 1) {Her tjekker koden to ting, før den gør noget. Først om artikelindstillingerne er slået til. Derefter om publiceringsindstillingerne også er slået til.
Det er vigtigt, fordi feltet kun skal flyttes, hvis de relevante områder i Joomla-formularen faktisk bliver vist. Ellers ville koden forsøge at flytte feltet til et område, som måske slet ikke findes i den aktuelle visning.
$browserPageTitleField = $this->;form->;renderField('article_page_title', 'attribs');Her henter Joomla selve feltet Browser Page Title og gør det klar til visning.
Man kan tænke på det som: “Tag det færdige felt, som Joomla normalt selv ville vise, og gem det midlertidigt, så vi kan vise det et andet sted senere.”
Det smarte er, at feltet stadig er Joomlas eget felt. Label, input, værdi, validering og gemmefunktion bliver ikke ændret.
$this->;form->;removeField('article_page_title', 'attribs');Her fjernes feltet fra sin oprindelige placering i formularen.
Det betyder ikke, at feltet slettes fra Joomla eller databasen. Det betyder kun, at Joomla ikke længere skal vise det dér, hvor det normalt ville blive vist.
Hvis denne linje ikke var med, ville feltet blive vist to gange: både under sin gamle placering og på den nye placering.
Indsæt feltet sammen med metadata
Derefter udskiftes denne betingelse:
<?php if ($params->;get('show_publishing_options', 1) == 1) : ?>med denne:
<?php if ($showPublishingOptions == 1) : ?>Og feltet indsættes lige over metadata:
<?php echo $browserPageTitleField; ?>Det betyder i praksis, at Browser Page Title nu bliver vist sammen med Meta Description og de øvrige SEO-felter.
Resultatet er et mere naturligt workflow i artikelredigeringen, fordi de vigtigste SEO-felter nu er samlet samme sted i stedet for spredt ud over flere faner i administratoren.

Du kan få koden jeg har brugt til den nye edit.php her:
<?php
/**
* @package Joomla.Administrator
* @subpackage com_content
*
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
/** @var \Joomla\Component\Content\Administrator\View\Article\HtmlView $this */
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\Router\Route;
use Joomla\Registry\Registry;
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = $this->getDocument()->getWebAssetManager();
$wa->getRegistry()->addExtensionRegistryFile('com_contenthistory');
$wa->useScript('keepalive')
->useScript('form.validate')
->useScript('com_contenthistory.admin-history-versions');
$this->configFieldsets = ['editorConfig'];
$this->hiddenFieldsets = ['basic-limited'];
$fieldsetsInImages = ['image-intro', 'image-full'];
$fieldsetsInLinks = ['linka', 'linkb', 'linkc'];
$this->ignore_fieldsets = array_merge(['jmetadata', 'item_associations'], $fieldsetsInImages, $fieldsetsInLinks);
$this->useCoreUI = true;
// Create shortcut to parameters.
$params = clone $this->state->get('params');
$params->merge(new Registry($this->item->attribs));
$input = Factory::getApplication()->getInput();
$assoc = Associations::isEnabled();
$showArticleOptions = $params->get('show_article_options', 1);
$showPublishingOptions = $params->get('show_publishing_options', 1);
$browserPageTitleField = '';
if ($showArticleOptions && $showPublishingOptions == 1) {
$browserPageTitleField = $this->form->renderField('article_page_title', 'attribs');
$this->form->removeField('article_page_title', 'attribs');
}
if (!$assoc || !$showArticleOptions) {
$this->ignore_fieldsets[] = 'frontendassociations';
}
if (!$showArticleOptions) {
// Ignore fieldsets inside Options tab
$this->ignore_fieldsets = array_merge($this->ignore_fieldsets, ['attribs', 'basic', 'category', 'author', 'date', 'other']);
}
// In case of modal
$isModal = $input->get('layout') === 'modal';
$layout = $isModal ? 'modal' : 'edit';
$tmpl = $input->get('tmpl');
$tmpl = $tmpl ? '&tmpl=' . $tmpl : '';
?>
<form action="<?php echo Route::_('index.php?option=com_content&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" aria-label="<?php echo Text::_('COM_CONTENT_FORM_TITLE_' . ((int) $this->item->id === 0 ? 'NEW' : 'EDIT'), true); ?>" class="form-validate">
<?php echo LayoutHelper::render('joomla.edit.title_alias', $this); ?>
<div class="main-card">
<?php echo HTMLHelper::_('uitab.startTabSet', 'myTab', ['active' => 'general', 'recall' => true, 'breakpoint' => 768]); ?>
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'general', Text::_('COM_CONTENT_ARTICLE_CONTENT')); ?>
<div class="row">
<div class="col-lg-9">
<div>
<fieldset class="adminform">
<?php echo $this->form->getLabel('articletext'); ?>
<?php echo $this->form->getInput('articletext'); ?>
</fieldset>
</div>
</div>
<div class="col-lg-3">
<?php echo LayoutHelper::render('joomla.edit.global', $this); ?>
</div>
</div>
<?php echo HTMLHelper::_('uitab.endTab'); ?>
<?php // Do not show the images and links options if the edit form is configured not to. ?>
<?php if ($params->get('show_urls_images_backend') == 1) : ?>
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'images', Text::_('COM_CONTENT_FIELDSET_URLS_AND_IMAGES')); ?>
<div class="row">
<div class="col-12 col-lg-6">
<?php foreach ($fieldsetsInImages as $fieldset) : ?>
<fieldset id="fieldset-<?php echo $fieldset; ?>" class="options-form">
<legend><?php echo Text::_($this->form->getFieldsets()[$fieldset]->label); ?></legend>
<div>
<?php echo $this->form->renderFieldset($fieldset); ?>
</div>
</fieldset>
<?php endforeach; ?>
</div>
<div class="col-12 col-lg-6">
<?php foreach ($fieldsetsInLinks as $fieldset) : ?>
<fieldset id="fieldset-<?php echo $fieldset; ?>" class="options-form">
<legend><?php echo Text::_($this->form->getFieldsets()[$fieldset]->label); ?></legend>
<div>
<?php echo $this->form->renderFieldset($fieldset); ?>
</div>
</fieldset>
<?php endforeach; ?>
</div>
</div>
<?php echo HTMLHelper::_('uitab.endTab'); ?>
<?php endif; ?>
<?php echo LayoutHelper::render('joomla.edit.params', $this); ?>
<?php // Do not show the publishing options if the edit form is configured not to. ?>
<?php if ($showPublishingOptions == 1) : ?>
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'publishing', Text::_('COM_CONTENT_FIELDSET_PUBLISHING')); ?>
<div class="row">
<div class="col-12 col-lg-6">
<fieldset id="fieldset-publishingdata" class="options-form">
<legend><?php echo Text::_('JGLOBAL_FIELDSET_PUBLISHING'); ?></legend>
<div>
<?php echo LayoutHelper::render('joomla.edit.publishingdata', $this); ?>
</div>
</fieldset>
</div>
<div class="col-12 col-lg-6">
<fieldset id="fieldset-metadata" class="options-form">
<legend><?php echo Text::_('JGLOBAL_FIELDSET_METADATA_OPTIONS'); ?></legend>
<div>
<?php echo $browserPageTitleField; ?>
<?php echo LayoutHelper::render('joomla.edit.metadata', $this); ?>
</div>
</fieldset>
</div>
</div>
<?php echo HTMLHelper::_('uitab.endTab'); ?>
<?php endif; ?>
<?php if (!$isModal && $assoc && $params->get('show_associations_edit', 1) == 1) : ?>
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'associations', Text::_('JGLOBAL_FIELDSET_ASSOCIATIONS')); ?>
<fieldset id="fieldset-associations" class="options-form">
<legend><?php echo Text::_('JGLOBAL_FIELDSET_ASSOCIATIONS'); ?></legend>
<div>
<?php echo LayoutHelper::render('joomla.edit.associations', $this); ?>
</div>
</fieldset>
<?php echo HTMLHelper::_('uitab.endTab'); ?>
<?php elseif ($isModal && $assoc) : ?>
<div class="hidden"><?php echo LayoutHelper::render('joomla.edit.associations', $this); ?></div>
<?php endif; ?>
<?php if ($this->canDo->get('core.admin') && $params->get('show_configure_edit_options', 1) == 1) : ?>
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'editor', Text::_('COM_CONTENT_SLIDER_EDITOR_CONFIG')); ?>
<fieldset id="fieldset-editor" class="options-form">
<legend><?php echo Text::_('COM_CONTENT_SLIDER_EDITOR_CONFIG'); ?></legend>
<div class="form-grid">
<?php echo $this->form->renderFieldset('editorConfig'); ?>
</div>
</fieldset>
<?php echo HTMLHelper::_('uitab.endTab'); ?>
<?php endif; ?>
<?php if ($this->canDo->get('core.admin') && $params->get('show_permissions', 1) == 1) : ?>
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'permissions', Text::_('COM_CONTENT_FIELDSET_RULES')); ?>
<fieldset id="fieldset-rules" class="options-form">
<legend><?php echo Text::_('COM_CONTENT_FIELDSET_RULES'); ?></legend>
<div>
<?php echo $this->form->getInput('rules'); ?>
</div>
</fieldset>
<?php echo HTMLHelper::_('uitab.endTab'); ?>
<?php endif; ?>
<?php echo HTMLHelper::_('uitab.endTabSet'); ?>
<?php // Creating 'id' hiddenField to cope with com_associations sidebyside loop ?>
<?php if ($params->get('show_publishing_options', 1) == 0) : ?>
<?php $hidden_fields = $this->form->getInput('id'); ?>
<div class="hidden"><?php echo $hidden_fields; ?></div>
<?php endif; ?>
<?php echo $this->form->renderControlFields(); ?>
</div>
</form>
Små backend-forbedringer gør større forskel end mange tror
Noget af det mest undervurderede i CMS-arbejde er friktion.
Hvis redaktører konstant skal lede efter felter eller skifte mellem faner, bliver arbejdet langsommere og mere fejlbehæftet. Det gælder især SEO, hvor mange små detaljer skal udfyldes konsekvent.
Ved at samle Browser Page Title og Meta Description samme sted bliver arbejdsgangen mere naturlig. Det lyder som en lille ændring, men i praksis gør det backend mere logisk at arbejde i.
Og det er i virkeligheden en af Joomlas største styrker: at systemet kan formes efter workflowet – ikke omvendt.
Joomla backend er fleksibel
Mange forbinder Joomla customisering med frontend, templates eller moduler. Men administrator-backenden er mindst lige så fleksibel.
Med overrides, layouts og Joomla Form API kan man ændre overraskende meget uden at kompromittere updates eller stabilitet.
Det er også derfor, Joomla stadig er interessant i større og mere specialiserede projekter. Systemet giver mulighed for at bygge workflows, der passer til organisationen – i stedet for at tvinge organisationen til at arbejde efter systemets standardopsætning.
-
Undgå core hacks
Direkte ændringer i Joomla core skaber problemer ved opdateringer og bør undgås i professionelle løsninger. -
Brug administrator overrides
Overrides gør det muligt at ændre visningen uden at ændre den underliggende Joomla-logik. -
Optimer workflowet
Små ændringer i backend kan gøre det lettere for redaktører at arbejde konsekvent med SEO.
Et lille override med stor praktisk effekt
Det her er måske ikke den mest spektakulære Joomla-tilpasning.
Men det er et godt eksempel på forskellen mellem bare at bruge et CMS – og faktisk optimere det til den måde, man arbejder på.
For professionelle Joomla-sites handler gode løsninger sjældent kun om flere funktioner. Det handler ofte om at reducere friktion, forbedre workflow og gøre det lettere at arbejde konsekvent.
Og nogle gange starter det bare med at flytte ét felt til det sted, hvor det hele tiden burde have ligget.

