Traits
Table of Contents
Es ist möglich Objekten und ObjektTemplates eigene Methoden zu geben. Diese werden jedoch nicht in der generierten Klasse geschrieben (da diese sonst beim nächsten ConfigReload gelöscht werden würden), sondern in eigenen Traits. Diese Traits müssen im Ordner "kon2/objects/traits/" definiert werden und müssen in dem Namespace "\com\setasign\Konquadrat\Object\Custom\Traits" (+ eventuelle Unter-Namespaces) sein.
Wenn ein neuer Trait erstellt wird, wird dieser erst gezogen, sobald der nächste ConfigReload ausgeführt wird.
In dem Trait ist $this auf jeden Fall ein AbstractObject! Da in PHP leider kein trait-require möglich ist wie z.B. in Hack, haben IDEs Probleme damit alle verfügbaren Methoden anzuzeigen. Als einfachen Workaround kann man in PHPStorm an den Trait im DocBlock die Annotation "@mixin \com\setasign\Konquadrat\Object\Custom\{Name}" machen.
Da alle eigenen Traits in dem selben Namespace liegen und auch die gleichen Namen haben wie die generierten Klassen und Interfaces, sollte in den Traits darauf geachtet werden, dass die TypeHints auf andere Konquadrat-Objekte nicht auf die Traits gemacht werden, sondern auf die generierten Klassen / Interfaces! Da es dabei aber zu doppelten Klassennamen in einem Namespace kommen kann, sollten unbedingt alle Namespace-Uses auf Klassen / Interfaces im Namespace "\com\setasign\Konquadrat\Object\Custom" einen Alias verwenden (bewährt hat sich Klassen- / Interfacename + 'Object').
Spezielle Methoden
In den Traits gibt es einige spezielle Methoden die möglich sind:
public function getTabHeader(): string;
Beschriftung des Tabs im Backend.
public function get{FieldName}();
Diese Methode wird aufgerufen, wenn ein get() gemacht wird. Z.B. wenn get('Name') aufgerufen wird, wird falls vorhanden getName() aufgerufen. Kann verwendet werden um Felder speziell zu formatieren. Die get()-Methoden werden vor dem Speichern eines Objektes ebenfalls abgefragt.
public function set{FieldName}($value);
Diese Methode wird aufgerufen, wenn ein set() gemacht wird. Z.B. wenn set('Name', 'Ich') aufgerufen wird, wird falls vorhanden setName('Ich') aufgerufen. Kann verwendet werden um Felder speziell zu formatieren oder zu validieren. Es muss darauf geachtet werden, ob AbstractObject::$isSettingData true ist. Falls ja sollten keine Fehler geworfen werden o.ä. da ansonsten das Objekt nicht verwendet werden kann (auch nicht um den Fehler zu beheben). Das Flag steht auf true wenn die Daten aus der Datenbank in das Objekt eingefügt werden. Falls man zumindest im Backend auf den Fehler aufmerksam zu machen ohne erst speichern zu müssen, ist es möglich eine Meldung in der MessageList zu hinterlegen.
public function getAs{SomeThing}(*): File;
Helfer um aus dem Objekt eine Datei zu generieren z.B. ein Kalendertermin oder eine Rechnung.
Die Parameter werden über das Di injektet (mehr dazu hier).
public function {actionName}Action(*);
Helfer um bestimmte Aktionen aus dem Backend heraus auszuführen. Beispiel: Email::sendAction()
Die Parameter werden über das Di injektet (mehr dazu hier).
public function init{Type}(*): void;
public function wakeup{Type}(*): void;
public function initAndWakeup{Type}(*): void;
Helfer um das ObjektTemplate/Objekt zu initialisieren. Die Methode muss exakt gleich heißen wie das ObjektTemplate / Objekt, also für das Objekt 'Teilnehmer' muss die Methode 'initTeilnehmer' heißen ('\' müssen durch '_' ersetzt werden).
- init*() wird aufgerufen wenn eine neue Instanz erstellt wird.
- wakeup*() wird aufgerufen wenn eine Instanz deserialisiert wird.
- initAndWakeup*() wird in beiden Fällen aufgerufen.
In den beiden wakeup-Methoden darf nicht auf die Session zugegriffen werden! Da diese Methoden während des deserialisierens der Session aufgerufen werden und diese noch nicht verfügbar ist.
Übliche Anwendungen:
- injekten von benötigten Abhängigkeiten (Abhängigkeiten die nur für bestimmte Actions benötigt werden, sollten eher in der entsprechenden Action injectet werden)
- füllen von der Property AbstractObject::$sleep
- registrieren von onCreate, beforeSave und afterSave Callbacks
Die Parameter werden über das Di injektet (mehr dazu hier).
Überschreiben von Methoden
Es ist möglich eine Methode die bereits in einem ObjektTemplate definiert wurde zu überschreiben. Das Auflösen von dem Konflikt wird automatisch beim ConfigReload gemacht anhand von Trait-Use-Konfliktauflösung. Die Methode aus dem implementierendem Objekt / ObjektTemplate hat hierbei Vorrang.
Es ist jedoch nicht möglich zwei gleichnamige Methoden auf gleicher Ebene zu implementieren. Also wenn z.B. das ObjektTemplate "AddressTpl" eine Methode "testen()" implementiert und das ObjektTemplate "HasEmailTpl" ebenfalls eine Methode "testen()" implementiert, dann ist es nicht möglich beide ObjektTemplates gemeinsam in einem Objekt oder ObjektTemplate zu verwenden ausser dieses Objekt / ObjektTemplate implementiert ebenfalls eine eigene "testen()"-Methode und überschreibt damit beide Methoden!
Beim Schreiben von Methoden in Traits sollte daran gedacht werden, dass die Mehrfachvererbung bei Konquadrat für Methoden und Properties nur 'imaginär' ist (siehe Technische Details zur Klassenstruktur)! Es ist unter keinen Umständen möglich eine 'überschriebene' Methode von einem ObjektTemplate zu verwenden, da diese nie importiert wurde, sondern ersetzt wurde durch use insteadof.
