LmbObject API

Aus Limbas Wiki

Wechseln zu: Navigation, Suche

<-- zurück zu Admin-Dokumentation / <-- zurück zur Hauptseite


Was bietet die neue API - ein Überblick

Die neue API bietet Ihnen die Möglichkeit eine Datenbanktabelle als Objekt zurückzugeben und auf diesem Objekt verschiedene Methoden auszuführen. Möchten Sie zum Beispiel ein Objekt Kunde mit den Attributen ID, Name und Namenszusatz, erhalten Sie dieses durch den folgenden Aufruf:

$lrKunde = LimbasRecord::model('KUNDEN', array('ID', 'NAME', 'NAME_ZUSATZ'));

Allgemein lautet der Aufruf:

$object = LimbasRecord::model($tableName, $attributes=null);

Zurückgegeben wird eine statische Instanz der genannten LimbasRecord Klasse, im Beispiel Kunden, an der anschließend die Klassenmethoden aufgerufen werden können.

An einer solchen Objektinstanz können nun nicht nur Methoden ausgeführt werden, sondern auch mit diesem Objekt verknüpfte Objekte zurückgegeben werden oder von diesem Objekt neue Objekte abgeleitet werden.

Möchten Sie beispielsweise die Kontakte zu einem Kunden, holen Sie sich zuerst das Objekt Kunden, mit den Attributen ID und Kontakte. Im nächsten Schritt holen Sie sich mit Hilfe der Funktion findById() den gewünschten Kunden und an diesem anschließend die Kontakte.

$lrKunde = LimbasRecord::model('KUNDEN', array('ID', 'Kontakte'));
$kunde = $lrKunde->findById(1);
$relation = $kunde->KONTAKTE();

Ein weiterer Teil der neuen API ist die Möglichkeit sich Logging-Protokolle erstellen zu lassen. Dabei haben Sie die Wahl sich die Ausgaben als einfache Logging Strings zurückgeben zu lassen, die Logging Strings in eine Datei ausgeben zu lassen oder als Webausgabe aufbereiten zu lassen.

Auch Darstellung der echo Ausgabe wurde für Objekte erweitert.

Quellen zur API

Den Source Code der API finden Sie im Verzeichnis limbas_src → extra → lmbObject. Er ist in drei Packages eingeteilt:

  • base: enthält die abstrakte Klasse LimbasComponent, in der einige der magischen Methoden behandelt werden, sowie die Klasse LimbasException.
  • db: enthält die Klassen LimbasRecord und LimbasRelation, die beide von der Klasse LimbasComponent erben und die Klasse LimbasRecordException die von der Klasse LimbasException erbt. Bei der Klasse LimbasRecord handelt es sich um die Schnittstelle zur Datenbank, die Klasse LimbasRelation stellt die Verknüpfung zwischen zwei Datenbanktabellen dar.
  • Log: enthält das Interface LimbasLogRoute , die Klassen LimbasPlainLogRoute, LimbasWebLogRoute und LimbasFileLogRoute, die das Interface LimbasLogRoute implementieren und die Logeinträge entweder „unbehandelt“ ausgeben, für das Web aufbereiten oder in eine Datei speichern und die Klasse LimbasLogger in der die einzelnen Loggingeinträge gesammelt werden.

LimbasRecord

Beschreibung der wichtigsten Methoden der Klasse LimbasRecord

Im Folgenden werden die wichtigsten Methoden der Klasse LimbasRecord beschrieben die für die Verwendung in einer Erweiterung möglich sind.

public static function model($tableName, $attributes=null)

Die zentrale Methode der Klasse ist public static function model($tableName, $attributes=null). Sie gibt ein statisches Modell der genannten Limbas Klasse zurück. An dieser statischen Klasseninstanz können anschließend die Klassenmethoden aufgerufen werden. Als Parameter werden der Tabellenname und die zu verwendenden Attribute benötigt.

public function findAll($criteria)

Mit der Funktion findAll($criteria)können an der ermittelten Klasseninstanz alle Datensätze, die den mitgegebenen Kriterien entsprechen, abgefragt werden. Sehen Sie sich dazu folgendes Beispiel an:

$lrKunde = LimbasRecord::model('KUNDEN', array('ID', 'NAME', 'NAME_ZUSATZ'));
$criteria = array('limit' => 3, 'page' => 18, 'sort' => array('NAME' => LimbasRecord::SD_ASC));
$kunden = $lrKunde->findAll($criteria);
for($i=0; $i<count($kunden); $i++) {
  $kunde = $kunden[$i];
  echo '' . ($i+1) . '. Kunde
echo $kunde; // calls __toString' . $kunde . '
'; } echo '</div>';

Zuerst wird mit „model“ das Objekt „Kunden“ geholt. In der nächsten Zeile werden die Kriterien für die Funktion findAll definiert. Sie besagen, dass maximal drei Datensätze, der Seite 18 ausgegeben werden, aufsteigend nach dem Namen sortiert. Anschließend wird die Funktion findAll am Objekt $lrKunde ausgeführt und die Datensätze an $kunden zurückgegeben. Zum Abschluss werden die geholten Datensätze in einer for-Schleife durchlaufen und mit echo ausgegeben. Dabei wird intern die magische Methode __toString aufgerufen.

http://limbas.com/images/wiki/de/admin/tools_erweiterungen/EchoKunden.png

public function findById($id)

Entsprechend funktioniert auch die Funktion findById($id). Hier wird anstatt allen Datensätzen der Datensatz mit der mitgegebenen Id zurückgegeben.

public function save($runValidation=false, $attributes=null)

Die Funktion save speichert das Objekt an dem die Funktion aufgerufen wird. Dabei wird bei einem neuen Objekt intern die Funktion insert() aufgerufen, bei einem bereits bestehenden update(). Als Parameter wird übergeben, ob eine Validierung stattfinden soll und welche Attribute gespeichert werden sollen, wobei beide Parameter optional sind. Der Rückgabewert der Funktion ist true, wenn das Speichern erfolgreich war und false wenn nicht.

public function saveRelation($field, $other)

Ebenso wie das Objekt kann selbstverständlich auch die Beziehung von einem Objekt zum anderen gespeichert werden. Als Parameter wird dabei der Feldname des zu verknüpfenden Feldes und das zu verknüpfende Objekt übergeben. Der Rückgabewert der Funktion ist true, wenn das Speichern erfolgreich war und false wenn nicht.

public function delete()

Ein Objekt kann natürlich nicht nur gespeichert werden, sondern auch gelöscht. Hierzu gibt es die Funktion delete(), die einfach an dem zu löschenden Objekt aufgerufen wird.

getter-/setter-Methoden der Klasse LimbasRecord

In der Objektorientierung erfolgt der Zugriff auf die einzelnen Attribute in der Regel über getter und setter Methoden. Auch in der Klasse LimbasRecord gibt es zahlreiche getter- und setter- Methoden um auf die Attribute zugreifen zu können. Beispielhaft sei hier die Funktion zur Rückgabe der „Attributes“ gezeigt.

public function getAttributes() {
 return $this->attributes;
}

Mit Ausnahme der Funktion getDefinition($name) haben die getter-Funktionen keine Parameter die übergeben werden und sind immer entsprechend der gezeigten Funktion aufgebaut. Es gibt folgende weitere getter-Funktionen:

  • getAttributeIds()
  • getMappings()
  • getDefinitions()
  • getId()
  • getTable()
  • getTableId()
  • getClassName()
  • getFindMetaData().

Auch die setter-Funktionen sind einfache Funktionen wie folgendes Beispiel zeigt:

public function setAttributes($attributes) {
 $this->attributes = $attributes;
}

Es gibt folgende weitere setter-Funktionen:

  • setAttributes($attributes)
  • setDefinitions($definitions)
  • setId($id)
  • setLoading($loading).

Zustandsabfragen der Klasse LimbasRecord

Ein weiterer Bestandteil der Klasse LimbasRecord sind verschiedene Zustandsabfragen, die im positiven Fall true zurückgeben, ansonsten false. Dabei kann beispielsweise überprüft werden ob es ein Attribut mit dem übergebenen Namen gibt „isAttribute($name)“ oder ob sich der Datensatz geändert hat „isChanged()“. Weitere Zustandsabfragen sind:

  • isUsableAttribute($name),
  • isRelation($name)
  • isFromRelation($name)
  • isNew().

Transaktionshandling

Über die Funktionen startTransaction(), endTransaction() und rollbackTransaction() kann auf einfache Weise eine Datenbankaktion in einer Transaktion ausgeführt werden. Soll beispielsweise das Speichern eines neuen Kontaktes in einer Transaktion ablaufen sieht das wie folgt aus:

kontakt = new LimbasRecord('kontakte');
$kontakt->Name = 'Maier';
$kontakt->Vorname = 'Heinz';
LimbasRecord::startTransaction();
$kontakt->save();
LimbasRecord::endTransaction();

Die Transaktion wird mit startTransaction() gestartet und braucht bei Beendigung zwingend den Aufruf endTransaction().

LimbasRelation

Welche Methoden gibt es für das verknüpfte Objekt

Die Klasse LimbasRelation stellt die Verknüpfung von zwei Datenbankobjekten dar und beinhaltet die Funktionen um an dieser Verknüpfung Veränderungen vorzunehmen. Im Folgenden werden, wie für die Klasse LimbasRecord, die für die Verwendung in einer Erweiterung wichtigsten dieser Funktionen näher betrachtet.

Die Klasse LimbasRelation enthält bis auf zwei Ausnahmen nur getter- und setter- Funktionen und Abfragen, die überprüfen, ob ein bestimmtes Attribut oder Objekt vorhanden ist. Bei den beiden anderen Funktionen handelt es sich um die Funktionen addCriteria($name, $value), die einen „criteria Ausdruck“ hinzufügt und addObject($object) . Wie der Name schon sagt fügt addObject($object) ein Objekt hinzu, um genau zu sein ein verknüpftes Objekt. In der Funktion wird dabei zuerst ein Logging-Eintrag erstellt. Nach einer Überprüfung, ob es sich um ein Objekt der richtigen Datenbanktabelle handelt wird es im positiven Fall zu der Liste der verknüpften Objekte hinzugefügt. Im negativen Fall wird eine LimbasRecordException geworfen.

getter-/setter- Funktionen

Die getter Funktionen haben auch hier alle den gleichen Aufbau.

public function getObjects() {
 $this->log('LimbasRelation(' . $this->refId . ', ' . $this->definition['name'] . ').getObjects ' . count($this->objects));
 return $this->objects;
}

Im ersten Schritt wird eine log-Nachricht geschrieben, im zweiten wird ein Array der entsprechenden Objekte zurückgegeben. Außer der im Beispiel zu sehenden getObjects() gibt es noch die Funktionen

  • getStrings()
  • getCriteria()
  • getAttributes().

Auch die setter-Funktionen sehen im Wesentlichen alle gleich aus. Zuerst wird eine log-Nachricht geschrieben, anschließend werden die Objekte ersetzt.

public function setCriteria($criteria) {
 $this->log('LimbasRelation(' . $this->refId . ').setCriteria(' . var_export($criteria, true) . ')');
 $this->criteria = $criteria;
}

Es unterscheidet sich lediglich die Funktion setObject($objects) leicht von diesem Schema.

public function setObjects($objects) {
 $this->log('LimbasRelation(' . $this->refId . ', ' . $this->definition['name'] . ').setObjects(' . count($objects) . ')');
 $this->objects = array();
 foreach($objects as $object) {
  $this->addObject($object);
 }
}

Hier werden die übergebenen Objekte in einer Schleife durchlaufen und für jedes der Objekte wird die Funktion addObject($object) ausgeführt.

Zuletzt gibt es noch die beiden Funktionen hasObjects() und hasStrings(), die jeweils überprüfen, ob es Objekte bzw. Strings gibt und im positiven Fall true zurückgeben, ansonsten false.

Magic Methods

In objektorientiertem PHP gibt es sogenannte „magic methods“. Diese magischen Methoden werden bei bestimmten Aktionen automatisch von PHP aufgerufen. Sie beginnen immer mit einem doppelten Unterstrich, weshalb diese Notation nicht für andere Funktionen verwendet werden sollte. In PHP gibt es folgende magische Methoden:

  • __construct()
  • __destruct()
  • __call()
  • __callStatic()
  • __get()
  • __set()
  • __isset()
  • __unset()
  • __sleep()
  • __wakeup()
  • __toString()
  • __invoke()
  • __set_state()
  • __clone()
  • __autoload()

Zur näheren Erläuterung magischer Funktionen betrachten wir die Methode __construct(). Jede Klasse besitzt diese automatisch, sie kann aber auch mit einer neuen Funktionsweise überschrieben werden. Das folgende Beispiel zeigt die __construct() Methode der Klasse LimbasRecord. Als Parameter hat sie einen Tabellennamen von Limbas und zu verwendende Attribute. In der Methode wird zuerst die __construct() Methode der vererbenden Klasse aufgerufen, anschließend wird der Tabellennamen in Großschreibung geändert, ein Logeintrag gespeichert und die Methode createAttributes aufgerufen.

public function __construct($table, $attributes=null) {
 parent::__construct();
 $this->_table = strtoupper($table);
 $this->log('LimbasRecord(' . $this->refId . ').__construct ' . $this->_table);
 $this->createAttributes($attributes);
}

Möchte man zum Beispiel einen neuen Kunden erstellen und ruft $kunde = new LimbasRecord('kunden'); auf wird automatisch der beschriebene Konstruktor __construct() aufgerufen und die neue Klasse erstellt.

Wie funktioniert das Logging ?

Die Logging Funktionalität baut sich aus verschiedenen Klassen zusammen. Zunächst gibt es das Interface LimbasLogRoute. Dieses wird von den Klassen LimbasFileLogRoute, LimbasPlainLogRoute und LimbasWebLogRoute implementiert. In diesen Klassen werden die Log-Nachrichten für die entsprechenden Ausgabewege, d.h. Dateiausgabe, einfache Ausgabe und Webausgabe aufbereitet. Die Klasse LimbasLogger übernimmt die eigentliche Arbeit der Nachrichtensammlung und stellt dazu verschiedene Funktionen zur Verfügung:

  • log($str,$level=self::LL_INFO): Loggt einen String zum Logger (mit dem Loglevel LL_INFO)
  • trace($str): Traced einen String zum Logger (mit dem Loglevel LL_TRACE)
  • beginProfile($token)/endProfile($token): markiert den Beginn bzw. das Ende des Profiling
  • addLogRoute($route): fügt dem Logger eine Route hinzu.
  • getLogLines(): gibt den vollständigen Log zurück.
  • processLog(): verarbeitet den Log mit einer definierten Log-Route.
  • useExceptionHandler(): setzt den ExceptionHandler.
  • processException($exception): verarbeitet eine Exception.

Die Verwendung des Logging im Source Code ist denkbar einfach. Zu Beginn wird der Logger mit der gewünschten Logging-Ausgabe und der Exception Handler gesetzt.

LimbasLogger::addLogRoute(new LimbasWebLogRoute());
LimbasLogger::useExceptionHandler();

Mit beginProfile() und endProfile() wird anschließend der Bereich definiert für den ein Log-Protokoll erstellt werden soll. Abschließend wird mit echo LimbasLogger::processLog(); die Log-Ausgabe angestoßen.

Beispielhafte Verwendung von lmbObject

In einem Beispiel aus der Praxis soll gezeigt werden, wie einfach der Datenzugriff mit lmbObject erfolgen kann. Es handelt sich um folgende Aufgabenstellung: für das Backup Programm Bacula sollen die Konfigurationseinträge für die Elemente Clients, Pools, FileSets und Jobs generiert werden. Die Vorgehensweise für die einzelnen Elemente ist immer gleich, weshalb hier beispielhaft die „jobs“ behandelt werden, die Sie sich im folgenden Source Code genauer anschauen können.

<?php
$criteria = array();
$lrJob = LimbasRecord::model('bck_jobs', array('ID', 'ENABLED', 'NAME', 'TYPE', 'LEVEL', 'POOL', 'FILESET', 'SCHEDULE', 'JOBDEF', 'CLIENT', 'PRIORITY'));
$jobs = $lrJob->findAll($criteria);
foreach($jobs as $job)
{
 echo 'Job {'."\n";
 echo ' Name = '.$job->__get('NAME')."\n";
 echo ' Enabled = '.(($job->__get('ENABLED')) ? 'yes' : 'no')."\n";
 echo ' JobDefs = '.$job->__get('JOBDEF')."\n";
 echo ' Type = '.$job->__get('TYPE')."\n";
 echo ' Client = '.$job->client[0]."\n";
 echo ' FileSet = '.$job->fileset[0]."\n";
 echo ' Pool = '.$job->pool[0]."\n";
 echo ' Level = '.$job->__get('LEVEL')."\n";
 echo ' Schedule = '.$job->__get('SCHEDULE')."\n";
 echo ' Write Bootstrap = /var/lib/bacula/Client-'.$job->client[0].'.bsr'."\n";
 echo ' Priority = '.$job->__get('PRIORITY')."\n";
 echo '}'."\n\n";
}
?>

Zunächst wird die statische Instanz $lrJob der Klasse LimbasRecord mit den benötigten Attributen für die Datenbanktabelle bck_jobs erstellt. An diesem Objekt kann anschließend die Funktion findAll($criteria) aufgerufen werden, die alle Datensätze für die mitgegebenen Kriterien findet. Die gefundenen Jobs werden anschließend in einer Schleife foreach($jobs as $job) durchlaufen, um mit echo die Ausgabe für die Konfigurationseinträge zu erzeugen. Dabei wird über die Variable $job auf die benötigen Attribute zugegriffen (z.B. $job->__get('NAME') od. $job->client[0]).