Eigene JForm-Felder. Typ-Konflikte in Joomla-Formularen (Schutz durch Namespacing)
In Joomla kann man eigene Formularfelder programmieren und mittels addfieldpath
in JForm
-XML-Dateien bekannt machen. Alternativ geht das in PHP mit JForm::addFieldPath(...)
. Was aber, wenn man für das eigene Feld einen Namen (Typ, type
) verwendet, den Joomla schon verwendet oder eine andere zuinstallierte Erweiterung? Joomla wird das Formularfeld anzeigen, das es zuerst findet. Vielleicht das falsche.
Beispiel-Szenario
Nehmen wir an, wir haben ein Plugin namens testens
geschrieben. Das soll im Backend ein Formular anzeigen, um Plugin-Einstellungen machen zu können. Es soll also diverse Formularfelder anzeigen. Ganz normal in Joomla.
Im Formular befindet sich auch ein von uns selbst erstelltes JForm
-Feld, das ausschließlich einen fixen Text Hallo Welt! ausgeben soll.
Dafür haben wir ein eigenes Formularfeld vom Typ Spacer
im Ordner /plugins/system/testens/myfields/ angelegt. Also dort eine Datei ereugt namens spacer.php. Mit folgendem Code:
<?php
defined('JPATH_PLATFORM') or die;
class JFormFieldSpacer extends JFormField
{
protected $type = 'Spacer';
protected function getInput()
{
return ' ';
}
protected function getLabel()
{
return 'Hallo Welt!';
}
}
Unser Feld-Code gibt durch Zeile 16, so hoffen wir zumindest noch, wie im nächsten Bild zu sehen Hallo Welt! an seiner Labelposition aus. Sonst nix.
Wie man es eben so macht in Joomla-Formularen (JForms), trägt man dafür in die XML-Datei des Plugins, dem so genannten Erweitrungs-Manifest, im <config>
-Block innerhalb des <fields>
-Blocks mit Namen params
an der Wunschposition das eigene Feld mit type="spacer"
ein (Zeilen 20, 21 des folgenden Code-Ausschnittes).
<?xml version="1.0" encoding="utf-8"?>
<extension version="3.5" type="plugin" group="system" method="upgrade">
<name>PLG_SYSTEM_STRUCTUREDDATAGHSVS</name>
...
<config>
<fields name="params" addfieldpath="plugins/system/testens/myfields/">
<fieldset name="basic">
...
<field name="structureddata_only_robots" type="list" default="1"
label="Only robots"
description="Structured datas nur Robots zeigen">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field type="spacer" name="organizationlogospacer"
label="Egal_FUER_das_Tutorial"/>
...
</fieldset>
</fields>
</config>
</extension>
Zusätzlich befindet sich in Zeile 8 der Hinweis, wo Joomla nach eigenen Formularfeldern suchen soll. Mit dieser Anweisung addfieldpath="plugins/system/testens/myfields/"
wird Joomla in einer Methode addPath(...)
den Weg zu unserem eigenen Feld zu bereits anderweitig gesammelten Pfaden, wo Joomla auch sucht, hinzufügen.
Und jetzt folgt die Crux
Wir haben blöderweise nicht daran gedacht, dass im Joomla-Core ein JForm
-Formularfeld vom Typ Spacer
bereits existiert, das etwas anders funktioniert als unser eigenes.
Wenn Joomla bereits ein Feld vom selben Typ Spacer
sonstwo gefunden hat, ist es ein wenig Russich Roulette, welches nun in unserem Formular verwendet wird. Meistens gewinnt Joomla mit seinen eigenen Felder-Typen. Manchmal auch eine ganz andere Erweiterung, dessen Ersteller blöd wie wir war.
Wie im folgenden Bild zu sehen. Da steht nicht Hallo Welt!, sondern das oben im XML eingetragene Label Egal_FUER_das_Tutorial
wird durch das Spacer
-Feld von Joomla ausgegeben, weil das eben Feld-Labels ausgibt. Unser eigenes Formular-Feld interessiert das Label im Manifest dagegen überhaupt nicht. Kann also nur das joomlaeigene spacer
-Feld sein., was hier das Rennen gewonnen hat. Das ist der Typ-Konflikt, den die Überschrift des Beitrags meint.
Was kann man tun?
Entweder: Individueller, unverwechselbarer Name (Typ)...
... für das eigene Formularfeld, Ich könnte es z.B. spacerghsvs
nennen und die Codes und Dateinamen entsprechend umschreiben. Da ich vielleicht noch viele Erweiterungen schreiben werde, wo ich viele, aber unterschiedliche Spacerfelder programmieren werde... Weiß nicht, ob ich so kreativ bin... und die Übersicht behalte, welche Namen ich schon früher verwendet habe. Geht aber natürlich auch und wir sind fertig.
Oder: Namespacing verwenden
Klingt vielleicht komplizierter als es ist (das ewige Los der Autodidakten, die am Ende feststellen, dass die Akademiker gelegentlich über ganz einfache Sachen reden).
In obigem XML und PHP haben wir ein Feld vom Typ spacer
definiert. Die Klasse des Formularfelds (JFormFieldSpacer
, Zeile 4 in Code von spacer.php) benötigt in diesen Fällen explizit ein J
vorne dran, damit Joomla es findet. Das hat einfach damit zu tun, wie Joomla die Klassennamen der Formularfelder zum Finden und Prüfen und Laden zusammensetzt.
Ändere ich in obiger XML-Datei den Typ des Spacerfeldes auf type="testens.spacer"
statt nur type="spacer"
wie folgt
<field type="testens.spacer" name="organizationlogospacer"
label="Egal_FUER_das_Tutorial"/>
und ändere in der PHP-Datei noch den Klassennamen von JFormFieldSpacer
nach TestensFormFieldSpacer
class TestensFormFieldSpacer extends JFormField
wird ohne weitere Änderungen an Dateiname oder Inhalt der PHP-Datei spacer.php das eigene Formularfeld angezeigt.
Unverwechselbar ist dieser neu erfundene Namensraum Testens
aber so nicht wirklich, also nicht wirklich eindeutig/spezifisch für mein System-Plugin testens. Auch andere Erweiterungsprogrammierer könnten auf die selbe Idee kommen, einen Namespace Testens zu verwenden.
Man sollte also abwägen und in Joomla würde sich zum Beispiel besser ein eindeutiger Namensraum PlgSystemTestens für ein System-Plugin Testens im PHP-Code oben anbieten.
class PlgSystemTestensFormFieldSpacer extends JFormField
sowie dann in der XML-Datei
<field type="PlgSystemTestens.spacer" name="organizationlogospacer"
label="Egal_FUER_das_Tutorial"/>
Und weil ich zusätzlich sowieso an alle meine Erweiterungsnamen ein "ghsvs" anhänge, nicht um Werbung zu machen, sondern, um meine Erweiterungsnamen eindeutig zu machen, ende ich persönlich dann mit so Würmern wie class PlgSystemTestensGhsvsFormFieldSpacer extends JFormField
und im Manifest mit type="
, Nicht gerade handlich, manchmal nervig, aber sicher.PlgSystemTestensGhsvs
.spacer"