Ein Blick in ein Contao-Widget

Heute will ich das TextField betrachten. Ich möchte in einem Modul ein einfaches Formular umsetzen und natürlich will ich wenn möglich bestehenden Code wiederverwenden. Eine Textbox möchte ich mit dem Widget TextField umsetzen. Soweit ich das verstanden habe ist ein „Widget“ in Contao ein Element in einem Formular. Im Klassenkommentar der abstrakten Klasse Widget steht: „Provide methods to handle form widgets“. Wie sieht TextField nun aus und wie kann es verwendet werden?

In der Klasse TextField ist kein Konstruktor definiert, d. h. es wird der Konstruktor der Oberklasse Widget verwendet:

public function __construct($arrAttributes=false) ...

Der Parameter arrAttributes erwartet ein Array mit notwendigen und optionalen Parameter. Darunter fällt beispielsweise der Name des Elements.

Beispiel:

new TextField(array('name'=>'forename',
                    'storeValues'=>true,
                    'required'=>true,
                    'mandatory'=>true,
                    'id'=>'forename'));

Das gefällt mir natürlich nicht und ist meiner Meinung nach ein schlechter Programmierstil. Läßt man das (eigentlich erforderliche) Attribute „name“ weg, wird kein Fehler generiert, sondern eine Textbox ohne das Attribute erzeugt (jedes Eingabefeld sollte einen internen Bezeichnernamen erhalten). Der Konstruktor selbst ruft die Methode addAttributes auf, die über die Attribute iteriert und eine Schlüssel/Wert-Zuweisung vornimmt:

foreach ($arrAttributes as $k=>$v)
  $this->$k = $v;

Es werden hier also keine Funktionen aufgerufen (Setter), sondern direkt die Klassenvariablen genutzt. „Direkt“ ist unter PHP ein dehnbarer Begriff. In diesem Fall wird eine „magische Funktion“ aufgerufen, nämlich __set(). Die Methode __set() wird automatisch aufgerufen, wenn auf eine nicht definierte Eigenschaft einer Klasse schreibend zugegriffen wird. In der konkreten Implementierung der Funktion in der Klasse TextField findet sich eine große switch-Anweisung:

public function __set($strKey, $varValue)
{
  switch ($strKey)
  {
    case 'value':
      $this->varValue = deserialize($varValue);
      break;
 ...

Wie gesagt, über diesen Stil läßt sich streiten…

Aber schieben wir das mal zur Seite. Es muß ja erstmal nur funktionieren und nicht eine perfekte Softwarearchitektur sein. Kommen wir zur eigentlichen HTML-Generierung in der Methode generate():

public function generate()
{
  $type = $this->hideInput ? 'password' : 'text';
  if (!$this->multiple)
  {
    // html code eines Input-Elements wird erzeugt
  }
  ...
  // falls size größer als 0 ist...
  for ($i=0; $i<$this->size; $i++)
  {
    // html code eines Input-Elements wird erzeugt
  }
  return ErzeugtesHTML;
}

Wir sehen, dass das TextField je nach Typ eine Passwort- oder eine schlichte Textbox sein kann. Wiederum nicht schön finde ich, dass an zwei Stellen im Code praktisch gleicher HTML-Code generiert wird (einen Unterschied gibts nur beim Bezeichnername, nämlich die eckigen Klammern, die bei multiplen Eingabefeldern an den Name angehängt werden).

Zuletzt gibt es ein Attribut, dass bei der Generierung fest codiert wurde: onfocus=“Backend.getScrollOffset();“. Da ich das Eingabefeld in einem Frontend-Modul verwenden will, ist das für mich das Ausschlußkriterium, denn eine Javascript Objekt Backend gibt es dort nicht. Um den Javascript Fehler im Frontend zu verhindern, müßte ich die Klasse ableiten und die Methode generate() überschreiben. Dann kann ich jedoch auch eine eigene, saubere Implementierung verwenden.

Noch ein Wort zur Validierung möchte ich abschließend noch verlieren. Damit das Widget bei Aufruf von „$forename->value“ auch einen Wert zurückliefert muß vorher zwingend die Methode validate() aufgerufen werden. Die Wertzuweisung erfolgt erst bei erfolgreicher Validierung. Das ist für mich nicht intuitiv erschwert den Umgang mit der Klasse nochmals. Meiner Meinung nach sollte das Formular den Wert immer zurückliefern und die Methode validate() müßte durch das Formular aufgerufen werden (das Formular sollte für die Validierung seiner Elemente verantwortlich sein, die Elemente verantwortlich für den reinen Inhalt).

Ein Gedanke zu “Ein Blick in ein Contao-Widget

  1. Pingback: 7 Contao-Links – Billmann IT BLOG

Kommentar verfassen