Konfiguration

1. Übersicht

Das Konfigurations-Konzept des APF sieht eine Abstraktion des Zugriffs auf Konfigurationen vor. Dies ermöglicht es nicht nur beliebige Quellen (z.B. Dateien und Datenbanken), sondern auch beliebige Datei-Formate (z.B. INI, XML) anzusprechen.

Technisch wird diese Abstraktion durch die Trennung von Speicher-Format und Repräsentation sowie die Einführung von Format-abhängigen Zugriffs-Komponenten erreicht. Dazu existiert eine zentrale Instanz, die zur Verwaltung der Formate vorgesehen ist (ConfigurationManager) und konkrete Implementierungen für die gewünschten Formate (z.B. IniConfigurationProvider). Die einzelnen Provider lassen sich beim ConfigurationManager dann für ein definiertes Format registrieren.

Ein weiteres Merkmal ist die gemeinsame Definition der Repräsentation eines Konfigurations-Formates. Hierzu existiert das Interface Configuration, das von jedem Provider hinsichtlich dem lesenden und schreibenden Zugriffs implementiert werden muss.

2. Technisches Konzept

2.1. Konfigurations-Schema

Das technische Konzept der Konfigurations-Komponente des APF sieht vor, dass eine Konfiguration von folgenden Parametern abhängen kann:

  • Basis-Ordner Die mit dem Release mitgelieferten, Datei-basierten Provider folgen der Empfehlung, Programmcode und Konfiguration zu trennen. Aus diesem Grund erwarten diese die Konfigurations-Dateien alle unter dem Ordner /config, der parallel zu den Ordnern core, modules, ... angelegt ist.
  • Namespace: Dieser Teil beschreibt den physikalischen (oder virtuellen) Speicherort der Konfiguration relativ zum Basis-Ordner. Üblicherweise gleicht der Pfad dem Namespace der Applikation um die Zugehörigkeit auszudrücken. Wie auch bei der Einbindung von Klassen und Komponenten üblich, werden Namespace-Abschnitte durch "\" getrennt (wie auch PHP-Namespace-Bereiche).
  • Context: Der Context drückt die Verwendung einer Software (z.B. Modul) in einer umgebenden Anwendung (z.B. Webseite) aus. Da das APF für den Betrieb von beliebig vielen Installationen und Anwendungen aus einer Code-Basis ermöglichen möchte, kann der Context dazu genutzt werden, die Konfigurationen von Modulen innerhalb von mehreren Installationen zu unterscheiden.
  • Environment: Das Merkmal Environment ermöglicht eine Unterscheidung der Konfiguration hinsichtlich der Umgebung, in der eine Software eingesetzt wird (z.B. Test- oder Produktions-Umgebung). Damit lässt sich die Installation einer Anwendung durch jeweils für die Umgebungen vorhandenen Konfigurationen ohne Code-Anpassung auf den Ziel-Umgebungen erledigen.
  • Name: Der Name der Konfiguration definiert den physikalischen Datei-Namen für Datei-basierte Provider bzw. den virtuellen Namen einer Konfiguration für z.B. Datenbank-basierte Implementierungen.
  • Endung/Typ: Die Datei-Endung wird als Kenner für den Konfigurations-Typ genutzt. So lässt sich für einen bestimmten (Datei-)Typ ein entsprechender Provider registrieren.

Die folgende Tabelle beschreibt die einzelnen Teile nochmal im Detail:

Installations-Ordner Basis-Ordner Namespace Context Environment Name Endung/Typ
/APF /config widgets\calendar siteone DEV labels .xml

Hieraus ergibt sich folgender Datei-Name bzw. Pfad:

Code
/APF/config/widgets/calendar/siteone/DEV_labels.xml
Das hier gezeigte Schema ist das Standard-Schema des APF. Bitte beachten Sie, dass dieses je nach ConfigurationProvider-Implementierung variieren kann!

Bitte beachten Sie, dass die Werte Context und Environment üblicherweise in der Bootstrap-Datei (index.php) konfiguriert werden. Der Context kann dem Page-Controller und Front-Controller mit der Methode setContext() mitgeteilt werden, die Umgebung wird via Registry konfiguriert:

PHP-Code
use APF\core\frontcontroller\Frontcontroller; $fC = Singleton::getInstance(Frontcontroller::class); $fC->setContext('my\context'); echo $fC->start('...', '...'); // Environment-Definition für beide Anwendungfälle Registry::register('APF\core', 'Environment', 'TESTBOX');

Alle weiteren Parameter einer Konfigurations-Resource werden beim Laden derselben explizit oder implizit mitgegeben.

2.2. Software-Komponenten

Zur Definition der Software-Komponenten bringt das APF folgende Interfaces und Implementierungen mit:

  • ConfigurationManager: Die Komponente ConfigurationManager ist für die Verwaltung der ConfigurationProvider zuständig und fungiert als zentrale Komponente für den lesenden und schreibenden Zugriff auf Konfigurationen. Sie übernimmt die Auflösung des zuständigen Providers sowie das Caching von Konfigurationen, die innerhalb eines Request bereits geladen wurden.
  • Configuration: Das Interface Configuration beschreibt das Aussehen der Objekt-Repräsentation einer Konfiguration bzw. der Sektion einer Konfiguration. Jeder Provider stellt eine auf diesem Interface basierende Implementierung bereit. Dabei gilt, dass die Objekt-Repräsentation einer Konfiguration sich aus genau den Implementierungen zusammensetzt. Eine Sektion innerhalb einer Konfiguration wird wieder durch eine Instanz der Implementierung des zugehörigen Providers repräsentiert.
  • ConfigurationProvider: Der ConfigurationProvider (Interface) beschreibt die Implementierung eines Providers für ein bestimmtes Format. Es definiert diejenigen Methoden des Interfaces, die der ConfigurationManager nutzt um das Lesen und Schreiben an den zuständigen Provider zu delegieren.
  • ConfigurationException: Die genannte Exception wird gemäß API-Definition immer dann geworfen, wenn Fehler beim Konfigurations-Handling auftreten. Der Entwickler hat damit über ein try-catch-Konstrukt die Möglichkeit diese zu behandeln.

Um das Lesen und Schreiben von Konfigurationen zu vereinfachen, stehen in allen Klassen, die von APFObject erben die Methoden getConfiguration() und saveConfiguration() zur Verfügung. Das Löschen von Konfigurationen kann über die Methode deleteConfiguration() bewerkstellig werden.

Da Konfigurations-Dateien oft sensible Daten beinhalten, sollte der /config-Ordner und damit die Installation des APF nicht öffentlich zugänglich sein. Es wird daher empfohlen, die Dateien ausserhalb des Web-Roots aufzubewahren oder eine .htaccess-Datei mit dem Inhalt
Code
<Location "/path/to/APF/installation/config"> Order Allow,Deny Deny from all </Location>
im /config-Ordner zu platzieren.

3. Vorhandene Provider

Das Release des Adventure PHP Framework liefert bereits vier Provider-Implementierungen mit. Diese sind in den folgenden Kapiteln erläutert.

Neben der in diesem Kapitel beschriebenen Zugriffs-Möglichkeit auf Konfigurationen zeigt Kapitel 6.3 eine Vereinfachung über die Nutzung von Pfad-basierten Abfragen. Mit dieser lässt sich der Code kürzer und damit übersichtlicher gestalten. Hierbei gelten keine Einschränkungen und Sie können stets beiden Möglichkeiten in Ihrer Applikation nutzen.

3.1. INI-Provider

Der INI-Provider implementiert das Standard-Konfigurations-Format des APF. Bis zur Version 1.13 war dieses als einziges Format verfügbar und folgt dem Datei-Schema der ini-Datei.

Das Laden einer INI-Datei mit dem Inhalt

APF-Konfiguration
[showCaptcha] ActionClass = "APF\modules\captcha\biz\actions\ShowCaptchaImageAction"

(Auszug aus einer Front-Controller-Konfiguration) kann innerhalb eines Document-Controllers wie folgt erledigt werden:

PHP-Code
class FooController extends BaseDocumentController { public function transformContent() { $config = $this->getConfiguration('APF\widgets\calendar', 'labels.ini'); ... } }

Die Variable $config enthält nun eine Instanz der Klasse IniConfiguration - dem Format des IniConfigurationProvider -, der in der Standard-Konfiguration des APF mit dem Handling von Dateien mit der Endung .ini betraut ist.

Die Objekt-Struktur, die vom Provider zurückgegeben wird hängt dabei von der Definition der Konfigurations-Datei ab. Dabei gelten folgende "Regeln":

  • INI-Sektionen werden gemäß dem Schema des Interface Configuration als Sektionen zur Verfügung gestellt. Damit lässt sich die Sektions-Repräsentation der oben aufgeführten Konfiguration per
    PHP-Code
    $config->getSection('showCaptcha')
    abfragen.
  • Die Schlüssel einer Sektion werden als Werte innerhalb einer Sektion bereitgestellt. Konkrete Werte könne mit der Methode getValue() abgefragt werden:
    PHP-Code
    $config->getSection('showCaptcha')->getValue('InputParams')
  • Als eine Besonderheit des INI-Formates werden Schlüssel mit einem Punkt (".") zu Sub-Sektionen aufgelöst. Für die oben aufgeführte Konfiguration bedeutet das, dass die Sektion showCaptcha über eine Sub-Sektion FC verfügt. Konkrete Werte dieser Sektion können damit über
    PHP-Code
    $config->getSection('showCaptcha')->getSection('FC')->getValue('InputParams')
    abgefragt werden. Der Provider unterstützt beliebige Ebenen von Sub-Sektionen. Dabei ist jede Sektion für sich genommen wieder eine Instanz der Klasse IniConfiguration.

Der schreibende Zugriff gestaltet sich ebenso intuitiv:

PHP-Code
class BarController extends BaseDocumentController { public function transformContent() { $config = new IniConfiguration(); $section = new IniConfiguration(); $section->setValue('year_label', 'Jahr'); $section->setValue('month_label', 'Monat'); $section->setValue('day_label', 'Tag'); $config->setSection('global-labels', $section); $this->saveConfiguration('APF\widgets\calendar', 'labels.ini', $config); } }

Neben der gezeigten Vorgehensweise ist es auch jederzeit möglich, gelesene Konfigurationen nach einer Manipulation wieder zu speichern.

3.2. XML-Provider

Der XML-Provider unterstützt das APF-Konfigurations-Format. Hierzu wurde folgendes Schema definiert (Auszug aus der Konfiguration für den Data-Mapper des Gästebuch-Moduls):

XML-Code
<?xml version="1.0" encoding="UTF-8"?> <configuration> <section name="GuestbookMapper"> <property name="servicetype">NORMAL</property> <property name="class">APF\modules\guestbook2009\data\GuestbookMapper</property> <section name="conf"> <section name="db"> <property name="method">setConnectionName</property> <property name="value">guestbook2009</property> </section> <section name="orm"> <property name="method">setORMInitType</property> <property name="value">NORMAL</property> </section> </section> </section> </configuration>

Das Schema zeichnet sich durch folgende Punkte aus:

  • Die Konfiguration wird mit dem Tag configuration umschlossen. Sie bildet das Root-Element.
  • Eine Konfiguration besteht in der ersten Ebene - wie auch die INI-Konfiguration - aus Sektionen. Diese werden (in jeder Ebene) durch das Tag section deklariert. Eine Sektion erhält ihren Namen über das Attribut name.
  • Innerhalb einer Sektion können weitere Sektionen oder konkrete Werte mittels des property-Tag definiert werden. Letztere zeichnen sich durch einen Namen (Attribut name) und den Inhalt des Tags (Wert) aus.

Der Zugriff auf die Konfiguration gestaltet sich analog zu Kapitel 3.1:

PHP-Code
class FooService extends APFObject { public function doSomething() { $config = $this->getConfiguration('APF\modules\guestbook2009', 'serviceobjects.xml'); ... } }

Die Variable $config enthält nun eine Instanz der Klasse XmlConfiguration - dem Format des XmlConfigurationProvider. Die Objekt-Struktur, folgt dabei folgenden "Regeln":

  • XML-Sektionen der ersten Ebene werden gemäß dem Schema des Interface Configuration als Sektionen in der Konfiguration zur Verfügung gestellt. Damit kann die Sektion GuestbookMapper per
    PHP-Code
    $config->getSection('GuestbookMapper')
    abfragen.
  • Die property-Tags einer Sektion werden als Werte innerhalb dieser bereitgestellt. Konkrete Werte könne mit der Methode getValue() abgefragt werden:
    PHP-Code
    $config->getSection('GuestbookMapper')->getValue('servicetype')
  • Alle section-Tags innerhalb einer Sektion werden als Sub-Sektion zur Verfügung gestellt. Konkrete Werte der Sektion db können damit via
    PHP-Code
    $config ->getSection('GuestbookMapper') ->getSection('conf') ->getSection('db') ->getValue('method')
    abgefragt werden. Der Provider unterstützt beliebige Ebenen von Sub-Sektionen. Dabei ist jede Sektion für sich genommen wieder eine Instanz der Klasse XmlConfiguration.

Der schreibende Zugriff ist identisch zum INI-Format (hier am Beispiel der Veränderung einer geladenen Konfiguration):

PHP-Code
class FooService extends APFObject { public function doSomethingElse() { $config = $this->getConfiguration('APF\modules\guestbook2009', 'serviceobjects.xml'); $config->getSection('GuestbookMapper')->setValue('servicetype', APFService::SERVICE_TYPE_SINGLETON); $this->saveConfiguration('APF\modules\guestbook2009', 'serviceobjects.xml', $config); } }

3.3. Db-Provider

Der DbConfigurationProvider ist eine einfache Implementierung des APF-Konfigurations-Schema um Konfigurationen in der Datenbank abzulegen. Er unterstützt im Gegensatz zu den Formaten INI und XML nur eine flache Hierarchie (Konfiguration -> Sektion -> Wert), beherrscht jedoch die Zuordnung von Context-, Sprach- und Umgebungs-abhängigen Werten.

Zur Nutzung des Providers muss eine Datenbank-Tabelle der Form

SQL-Statement
CREATE TABLE IF NOT EXISTS `config_widgets_calendar` ( `context` varchar(50) NOT NULL, `language` varchar(5) NOT NULL, `environment` varchar(20) NOT NULL, `name` varchar(20) NOT NULL, `section` varchar(20) NOT NULL, `key` varchar(30) NOT NULL, `value` varchar(500) NOT NULL, `creationtimestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modificationtimestamp` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', PRIMARY KEY (`context`,`language`,`environment`,`name`,`section`,`key`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

angelegt werden. Gemäß dem in Kapitel Konfigurations-Schema aufgezeigten Adressierung von Konfigurationen kann ein in der Datenbank befindlicher wie folgt geladen werden:

PHP-Code
class FooController extends BaseDocumentController { public function transformContent() { $config = $this->getConfiguration('APF\widgets\calendar', 'labels.db'); ... } }

Die Variable $config enthält nun eine Instanz der Klasse DbConfiguration - dem Format des DbConfigurationProvider. Die Objekt-Struktur, folgt dabei folgenden "Regeln":

  • Sektionen (siehe Spalte section) werden durch Gruppierung der Werte unter jeweils gleichen Werten für eine Abrage nach context, language, environment und name als Elemente der ersten Ebene erzeugt. Eine Sektion kann damit wie bei den zuvor beschriebenen Formaten per
    PHP-Code
    $config->getSection('main')
    abfragen werden.
  • Werte innerhalb von Sektionen sind über die Methode getValue() zu erfragen:
    PHP-Code
    $config->getSection('main')->getValue('icon')
Auf Grund der schematischen Einschränkungen des Datenbank-Providers sollte dieser nur für einfache Konfigurationen verwendet werden. Um die Performance zu steigern eignet sich eine Kombination mit dem MemcachedConfigurationProvider.

Der schreibende Zugriff auf den Datenbank-Store gestaltet sich identisch zu den zuvor beschriebenen Formaten:

PHP-Code
class BarController extends BaseDocumentController { public function transformContent() { $config = $this->getConfiguration('APF\widgets\calendar', 'labels.db'); $config->getSection('main')->setValue('icon', 'calendar_big.png'); $this->saveConfiguration('APF\widgets\calendar', 'labels.db', $config); } }

3.4. Memcached-Provider

Der MemcachedConfigurationProvider unterstützt selbst keine eigenes Format, sondern ist eine Art "Mediator"-Provider, der einen bestehenden Provider für das Lesen und Schreiben nutzt, die Konfiguration jedoch für den schnellen Zugriff in einem Memcached-Store Request-übergreifend hält.

Sofern der Provider auf die Datei-Endung bzw. den Typ "mem" konfiguriert ist (siehe Konfiguration der Provider), so lässt sich eine Konfiguration wie folgt laden:

PHP-Code
class FooService extends APFObject { public function doSomething() { $config = $this->getConfiguration('APF\widgets\calendar', 'labels.mem'); ... } }

Die Variable $config beinhaltet nun die gewünschte Konfiguration. Dazu versucht der Provider die gewünschte Konfiguration aus dem Memcached-Store zu beziehen. Falls diese dort noch nicht vorhanden oder abgelaufen ist, wird die physikalische Datei geladen und in den Store geschrieben.

Das Schreiben einer Konfiguration aus dem Memcached-Store inkludiert das Update der Konfiguration im Speicher und auf dem persistenten Datenträger. Die folgende Code-Box zeigt ein Beispiel:

PHP-Code
class FooService extends APFObject { public function doSomethingElse() { $config = $this->getConfiguration('APF\widgets\calendar', 'labels.mem'); $config->getSection('global-labels')->setValue('day_label', 'Tag'); $this->saveConfiguration('APF\widgets\calendar', 'labels.mem', $config); } }

3.5. APC Provider

Der ApcConfigurationProvider unterstützt ebenso wie der MemcachedConfigurationProvider kein eigenes Format, sondern ist eine Art "Mediator"-Provider, der einen bestehenden Provider für das Lesen und Schreiben nutzt, die Konfiguration jedoch für den schnellen Zugriff in einem APC Shared Memory Segment Request-übergreifend hält.

Sofern der Provider auf die Datei-Endung bzw. den Typ "apc" konfiguriert ist (siehe Konfiguration der Provider), so lässt sich eine Konfiguration wie folgt laden:

PHP-Code
class FooService extends APFObject { public function doSomething() { $config = $this->getConfiguration('APF\widgets\calendar', 'labels.apc'); ... } }

Die Variable $config beinhaltet nun die gewünschte Konfiguration. Dazu versucht der Provider die gewünschte Konfiguration aus dem APC-Store zu beziehen. Falls diese dort noch nicht vorhanden oder abgelaufen ist, wird die physikalische Datei geladen und in den Store geschrieben.

Das Schreiben einer Konfiguration aus dem APC-Store inkludiert das Update der Konfiguration im Speicher und auf dem persistenten Datenträger. Die folgende Code-Box zeigt ein Beispiel:

PHP-Code
class FooService extends APFObject { public function doSomethingElse() { $config = $this->getConfiguration('APF\widgets\calendar', 'labels.apc'); $config->getSection('global-labels')->setValue('day_label', 'Tag'); $this->saveConfiguration('APF\widgets\calendar', 'labels.apc', $config); } }

3.6. PHP Provider

Der PhpConfigurationProvider ermöglicht es, beliebig verschachtelte, assoziative PHP-Arrays als Speicher-Format von Konfigurationen einzusetzen. Dies hat einerseits den Vorteil, dass die PHP-Array-Syntax sehr einfach zu schreiben und zu lesen ist und andererseits PHP-Mechanismen wie der Zugriff auf Konstanten genutzt werden können.

Das folgende Beispiel zeigt die in Kapitel 3.2 beschriebene XML-Konfiguration mit mehreren Sektionen und Werten als PHP-Konfiguration:

PHP-Code
return [ 'GuestbookMapper' => [ 'conf' => [ 'db' => [ 'method' => 'setConnectionName', 'value' => 'guestbook2009' ], 'orm' => [ 'method' => 'setORMInitType', 'value' => 'NORMAL' ] ], 'servicetype' => \APF\core\service\APFService::SERVICE_TYPE_NORMAL, 'class' => 'APF\modules\guestbook2009\data\GuestbookMapper' ] ];

Die Struktur der Konfiguration zeichnet sich durch folgende Merkmale aus:

  • Die Inhalte werden per return an den PhpConfigurationProvider übergeben.
  • Alle Array-Offsets mit einer direkten Zuweisung eines skalaren Werts werden als Eigenschaften verstanden.
  • Alle Array-Offsets, die wiederum ein Array enthalten werden als Sektionen verstanden, die wiederum weitere Sektionen und/oder Werte enthalten.

Der Zugriff auf die Konfiguration gestaltet sich analog zu Kapitel 3.1:

PHP-Code
class FooService extends APFObject { public function doSomething() { $config = $this->getConfiguration('APF\modules\guestbook2009', 'serviceobjects.php'); ... } }

Die Variable $config enthält nun eine Instanz der Klasse PhpConfiguration - dem Format des PhpConfigurationProvider. Die Objekt-Struktur, folgt dabei folgenden "Regeln":

  • PHP-Sektionen der ersten Ebene werden gemäß dem Schema des Interface Configuration als Sektionen in der Konfiguration zur Verfügung gestellt. Damit kann die Sektion GuestbookMapper per
    PHP-Code
    $config->getSection('GuestbookMapper')
    abfragen.
  • Die property-Tags einer Sektion werden als Werte innerhalb dieser bereitgestellt. Konkrete Werte könne mit der Methode getValue() abgefragt werden:
    PHP-Code
    $config->getSection('GuestbookMapper')->getValue('servicetype')
  • Alle section-Tags innerhalb einer Sektion werden als Sub-Sektion zur Verfügung gestellt. Konkrete Werte der Sektion db können damit via
    PHP-Code
    $config ->getSection('GuestbookMapper') ->getSection('conf') ->getSection('db') ->getValue('method')
    abgefragt werden. Der Provider unterstützt beliebige Ebenen von Sub-Sektionen. Dabei ist jede Sektion für sich genommen wieder eine Instanz der Klasse XmlConfiguration.

Der schreibende Zugriff ist identisch zum INI-Format (hier am Beispiel der Veränderung einer geladenen Konfiguration):

PHP-Code
class FooService extends APFObject { public function doSomethingElse() { $config = $this->getConfiguration('APF\modules\guestbook2009', 'serviceobjects.php'); $config->getSection('GuestbookMapper')->setValue('servicetype', APFService::SERVICE_TYPE_SINGLETON); $this->saveConfiguration('APF\modules\guestbook2009', 'serviceobjects.php', $config); } }

4. Erweitertes Handling von Konfigurationen

In vielen Anwendungsfällen ist es nicht nur notwendig, einzelne Konfigurations-Werte zu lesen, sondern alle Elemente einzubeziehen oder mehrere Werte aus der Konfiguration zu nutzen.

Für den ersten Anwendungsfall bietet das Interface Configuration die Methoden getSectionNames() und getValueNames() an. Diese geben alle Sektions- und Werte-Schlüssel zurück. So lassen sich beispielsweise über den folenden Quelltext alle Sektions-Namen ausgeben:

PHP-Code
foreach($config->getSectionNames() as $sectionName) { echo $sectionName; }

Um die Schlüssel der Werte einer Sektion auszugeben, kann folgender Code genutzt werden:

PHP-Code
foreach($section->getValueNames() as $valueName) { echo $valueName; }

Zur Manipulation von Konfigurations-Repräsentationen stehen gemäß Interface noch zwei weitere Methoden zur Verfügung: removeSection() und removeValue. Mit Hilfe dieser kann die Konfiguration

APF-Konfiguration
[Default] key1 = "value1" key2 = "value2" key3 = "value3"

mit dem PHP-Code

PHP-Code
$config = $this->getConfiguration('...', 'config.ini'); $section = new IniConfiguration(); $section->setValue('key1', 'value1'); $section->setValue('key3', 'value2'); $section->setValue('key2', 'value3'); $config->setSection('Special', $section); $config->getSection('Default')->removeValue('key2'); $this->saveConfiguration('...', 'config.ini', $config);

zu folgendem Ergebnis geführt werden:

APF-Konfiguration
[Default] key1 = "value1" key3 = "value3" [Special] key1 = "value1" key2 = "value2" key3 = "value3"

Zur Prüfung einer Konfiguration stellt das Interface Configuration zwei Methoden zur Verfügung: hasSection() und hasValue(). Mit Hilfe von hasSection() lässt sich prüfen, ob eine Sektion tatsächlich vorhanden ist. Nutzen Sie hasValue() um die gleiche Prüfung für Konfigurations-Werte vorzunehmen.

Der folgende Code kann dazu verwendet werden, eine fehlende Konfigurations-Sektion zu erkennen:

PHP-Code
$config = $this->getConfiguration('...', 'config.ini'); if($config->hasSection('Default')) { echo 'Sektion "Default" vorhanden!' } else { echo 'Sektion "Default" NICHT vorhanden!' }

Die Prüfung, ob der Wert key1 definiert ist, lässt sich wie folgt bewerkstelligen:

PHP-Code
$config = $this->getConfiguration('...', 'config.ini'); if($config->getSection('Default')->hasValue('key1')) { echo 'Wert "key1" vorhanden!' } else { echo 'Wert "key1" NICHT vorhanden!' }

5. Konfiguration der Provider

Die in Kapitel 3 genannten Provider unterstützen neben den genannten Features weitere, die in den folgenden Kapiteln näher beschrieben sind.

5.1. INI, XML- und PHP-Provider

Die Implementierungen für das INI-, XML- und PHP-Format ermöglichen es, das Format der Konfigurationen zu beeinflussen. Hierzu stehen die Schalter omitContext, omitEnvironment und activateEnvironmentFallback. Diese beeinflussen im wesentlichen den Aufbau des Pfades unter dem die Konfiguration erwartet wird, ermöglichen dadurch jedoch weitere Anwendungsfälle.

Bitte beachten Sie, dass nur der INI-Provider standardmäßig aktiviert ist. Alle anderen Provider (wie hier der XML-Provider) müssen manuell nach dem Einbinden der Datei bootstrap.php registriert werden. Dies funktioniert für den XML-Provider wie folgt:
PHP-Code
use APF\core\configuration\provider\xml\XmlConfigurationProvider; use APF\core\configuration\ConfigurationManager; ConfigurationManager::registerProvider('xml', new XmlConfigurationProvider());
5.1.1. Schalter omitComtext

Ist der Schalter omitContext aktiviert, wird der Context nicht mehr als Teil des Datei-Pfades erwartet. Es ergibt sich dann folgender Aufbau:

Installations-Ordner Basis-Ordner Namespace Environment Name Ending/Typ
/APF /config widgets\calendar DEV labels .xml

Dieser Mechanismus kann für Konfigurations-Dateien verwendet werden, die ohnehin unabhängig vom Context sind. Um die Möglichkeit der Context-abhängigen Konfiguration trotzdem parallel anbieten zu können, ist es mit der Implementierung der INI- und XML-Provider möglich, diese für mehrere Typen/Endungen zu registrieren.

Sollen innerhalb einer Applikation Dateien mit der Endung .lang als Sprach-Konfigurationen ohne Context konfigurierbar sein, so kann dies nach Einbinden der Datei bootstrap.php (z.B. in der index.php) durch Neu-Registrierung des INI- oder XML-Providers auf die Endung .lang passieren:

PHP-Code
use APF\core\configuration\provider\ini\IniConfigurationProvider; use APF\core\configuration\ConfigurationManager; $langProv = new IniConfigurationProvider(); $langProv->setOmitContext(true); ConfigurationManager::registerProvider('lang', $langProv);

Damit können Context-unabhängige Sprach-Konfigurationen beispielsweise mit dem <html:getstring />-Tag verwendet werden:

APF-Template
<html:getstring namespace="widgets\calendar" config="labels.lang" entry="key3" />

Da der genannte Tag ebenso den ConfigurationManager und den für die Endung registrierten Provider nutzt, ist diese Vorgehensweise auch für andere Anwendungsfälle (z.B. (Document-)Controller) möglich.

Sofern das beschrieben Verhalten auf für .ini-Dateien genutzt werdem soll, kann der INI-Provider nach dem Einbinden der bootstrap.php mit der aktivierten Option neu registriert werden. Dieses Vorgehen wird jedoch ausdrücklich nicht empfohlen, wenn Komponenten des APF eingesetzt werden, die Context-abhängige Konfigurationen benötigen.
5.1.2. Schalter omitEnvironment

Ist der Schalter omitEnvironment aktiviert, so wird die konfigurierte Umgebung nicht mehr als Teil des Datei-Namens der Konfigurations-Datei genutzt. Es ergibt sich folgender Aufbau:

Installations-Ordner Basis-Ordner Namespace Context Name Ending/Typ
/APF /config widgets\calendar siteone labels .xml

Dieser Mechanismus kann für Konfigurations-Dateien verwendet werden, die ohnehin unabhängig von der Umgebung sind. Um die Möglichkeit der Umgebungs-abhängigen Konfiguration trotzdem parallel anbieten zu können, ist es mit der Implementierung der INI- und XML-Provider möglich, diese für mehrere Typen/Endungen zu registrieren.

Ist es innerhalb einer Komponente nicht erforderlich, Konfigurationen abhängig von der Umgebung zu nutzen, können für diesen Anwendungsfall spezielle Datei-Endungen (z.B. .allini) genutzt werden. Die Registrierung eines solchen INI- oder XML-Providers kann wie im nächsten Code-Block beschrieben erfolgen:

PHP-Code
use APF\core\configuration\provider\ini\IniConfigurationProvider; use APF\core\configuration\ConfigurationManager; $langProv = new IniConfigurationProvider(); $langProv->setOmitEnvironment(true); ConfigurationManager::registerProvider('allini', $langProv);
5.1.3. Schalter activateEnvironmentFallback

Der Schalter activateEnvironmentFallback bewirkt, dass nicht vorhandene Umgebungs-abhängige Konfigurationen auf die DEFAULT-Umgebung gemappt werden. Dies ermöglicht das Anlegen von "Standard"-Umgebungs-Konfigurationen, die bei Bedarf pro Umgebung überschrieben werden. Das Pfad-Format wird durch das Aktivieren des Features nicht geändert und ist daher identisch zum Standard-Schema.

Soll das Feature für einen INI- bzw. XML-Provider aktiviert werden, so kann das wie folgt erledigt werden:

PHP-Code
use APF\core\configuration\provider\ini\IniConfigurationProvider; use APF\core\configuration\ConfigurationManager; // Neu-Konfiguration eines bestehenden Providers try { $prov = ConfigurationManager::retrieveProvider('lang'); } catch (ConfigurationException $e) { // Sofern der Provider noch nicht registriert wurde, // erstellen wir ihn "lazy" neu. $prov = new IniConfigurationProvider(); } $prov->activateEnvironmentFallback(true); ConfigurationManager::registerProvider('lang', $prov); // Konfiguration eines neuen Providers $prov = new IniConfigurationProvider(); $prov->activateEnvironmentFallback(true); ConfigurationManager::registerProvider('lang', $prov);
5.1.4. Schalter omitConfigSubFolder
Bitte beachten Sie, dass diese Funktion erst ab dem Release 2.1 verfügbar ist.

Im Auslieferungs-Zustand des APF werden alle Konfigurationen unter dem Basis-Ordner /config abgelegt (siehe Kapitel 2.1). Nutzen Sie für Ihre Konfigurations-Dateien bereits einen eigenen Ordner - dies lässt sich sehr einfach über eine angepasste ClassLoader-Konfiguration erreichen - ist der Basis-Ordner gegebenenfalls redundant. Beispiel:

Code
/path/to/project/src/... /path/to/project/conf/config/...

In diesem Fall lässt sich der Schalter omitConfigSubFolder nutzen um die Konfiguration direkt unter /path/to/project/conf ablegen zu können.

Das Pfad-Format wird durch das Aktivieren des Features nicht geändert und ist daher identisch zum Standard-Schema.

Soll das Feature für einen INI- bzw. XML-Provider aktiviert werden, so kann das wie folgt erledigt werden:

PHP-Code
use APF\core\configuration\provider\ini\IniConfigurationProvider; use APF\core\configuration\ConfigurationManager; // Neu-Konfiguration eines bestehenden Providers try { $prov = ConfigurationManager::retrieveProvider('lang'); } catch (ConfigurationException $e) { // Sofern der Provider noch nicht registriert wurde, // erstellen wir ihn "lazy" neu. $prov = new IniConfigurationProvider(); } $prov->setOmitConfigSubFolder(true); ConfigurationManager::registerProvider('lang', $prov); // Konfiguration eines neuen Providers $prov = new IniConfigurationProvider(); $prov->setOmitConfigSubFolder(true); ConfigurationManager::registerProvider('lang', $prov);

5.2. Db-Provider

Um den DbConfigurationProvider zu registrieren, ist folgender Quellcode nach dem Einbinden der Datei bootstrap.php notwendig:

PHP-Code
use APF\core\configuration\provider\db\DbConfigurationProvider; use APF\core\configuration\ConfigurationManager; ConfigurationManager::registerProvider('db', new DbConfigurationProvider('Live-DB'));

Der beschriebene Code registriert den Provider für die Endung .db und definiert die Datenbank-Verbindung, die zum Lesen und Schreiben der Konfigurationen genutzt werden soll.

Die Implementierung sieht vor, dass der Tabellen-Name abhängig vom Namespace ist, unter dem die Konfiguration abgelegt ist. Die Benennung der Tabelle folgt der Regel, dass zunächst alle Groß-Buchstaben durch Klein-Buchstaben ersetzt, "::" durch "_" ersetzt wird und dann alle Zeichen ausser Kleinbuchstaben und "_" ersetzt werden. Dieses Suffix bildet dann zusammen mit dem Präfix "config_" den Namen der Tabelle.

5.3. Memcached-Provider

Der MemcachedConfigurationProvider ist - wie bereits beschrieben - dazu gedacht, physikalisch vorhandene Konfigurationen für den schnelleren Zugriff in einem Memcached-Store zu halten und von dort zu beziehen. Hierzu benötigt der Provider die gewünschte Memcached-Verbindung und den Provider, der das Lesen und schreiben der physikalischen Konfiguration übernimmt.

Um den Provider zu registrieren, ist folgender Quellcode nach dem Einbinden der Datei bootstrap.php notwendig:

PHP-Code
use APF\core\configuration\provider\mem\MemcachedConfigurationProvider; use APF\core\configuration\ConfigurationManager; $mem = new Memcache(); $mem->addServer('localhost', 11211, true); $provider = new MemcachedConfigurationProvider('ini', $mem); $provider->setExpireTime(30); ConfigurationManager::registerProvider('mem',$provider);

Der beschriebene Code registriert den Provider für die virtuelle Endung .mem, definiert eine persistente Verbindung zu einem lokalen Memcached-Server und nutzt den bereits registrierten INI-Provider für das Laden und Speichern der Konfigurationen.

Weiterhin wird die Cache-Gültigkeitsdauer auf 30 Sekunden festgelegt. Standard ist 1 Tag.

Bitte beachten Sie, dass der Name der physikalisch gespeicherten Datei die Endung des im Konstruktor angegebenen Provider-Typen hat (im obigen Beispiel: .ini). Das bedeutet, dass beim ersten Aufruf von
PHP-Code
$this->getConfiguration('APF\widgets\calendar', 'labels.mem')
die physikalische Datei
Code
/APF/config/widgets/calendar/siteone/DEFAULT_labels.ini
(bzw. gemäß den Regel der Konfiguration des INI-Provider) geladen wird. Ab dem zweiten Aufruf und innerhalb der Cache-Gültigkeitsdauer wird die Konfiguration direkt aus dem Memcached-Store geladen und zurückgegeben.

Der Provider bietet auf Grund der Nutzung eines anderen Providers die Möglichkeit alle Provider, die physikalisch gespeicherte Daten nutzen, zwischen zu speichern.

5.4. APC-Provider

Der ApcConfigurationProvider ist - wie bereits beschrieben - dazu gedacht, physikalisch vorhandene Konfigurationen für den schnelleren Zugriff in einem APC Shared Memory Segment zu halten und von dort zu beziehen. Hierzu benötigt den Provider, der das Lesen und schreiben der physikalischen Konfiguration übernimmt.

Die übrige Konfiguration wird bereits durch die Konfigurationsdirektiven der php.ini zur Verfügung gestellt.

Um den Provider zu registrieren, ist folgender Quellcode nach dem Einbinden der Datei bootstrap.php notwendig:

PHP-Code
use APF\core\configuration\provider\apc\ApcConfigurationProvider; use APF\core\configuration\ConfigurationManager; $provider = new ApcConfigurationProvider('ini'); $provider->setExpireTime(60); ConfigurationManager::registerProvider('apc', $provider);

Der beschriebene Code registriert den Provider für die virtuelle Endung .apc und nutzt den bereits registrierten INI-Provider für das Laden und Speichern der Konfigurationen.

Weiterhin wird die Cache-Gültigkeitsdauer auf 60 Sekunden festgelegt. Standard ist 1 Tag.

Bitte beachten Sie, dass der Name der physikalisch gespeicherten Datei die Endung des im Konstruktor angegebenen Provider-Typen hat (im obigen Beispiel: .ini). Das bedeutet, dass beim ersten Aufruf von
PHP-Code
$this->getConfiguration('APF\widgets\calendar', 'labels.apc')
die physikalische Datei
Code
/APF/config/widgets/calendar/siteone/DEFAULT_labels.ini
(bzw. gemäß den Regel der Konfiguration des INI-Provider) geladen wird. Ab dem zweiten Aufruf und innerhalb der Cache-Gültigkeitsdauer wird die Konfiguration direkt aus dem APC-Store geladen und zurückgegeben.

Der Provider bietet auf Grund der Nutzung eines anderen Providers die Möglichkeit alle Provider, die physikalisch gespeicherte Daten nutzen, zwischen zu speichern.

6. Lesen und Schreiben von Konfigurationen

6.1. Nativer Zugriff

Die vorangegangenen Kapitel haben gezeigt, wie Konfigurationen mit den in der Klasse APFObject vorhandenen Methoden gelesen und geschrieben werden kann. Neben dieser Vorgehensweise kann der ConfigurationManager natürlich auch direkt verwendet werden. Hierbei handelt es sich um eine statische Komponente, die wie ein Singleton von überall zugegriffen werden kann. Der Zugriff gestaltet sich dabei wie folgt:

PHP-Code
use APF\core\configuration\ConfigurationManager; // Laden einer Konfiguration $config = ConfigurationManager::loadConfiguration( $namespace, $context, $language, $environment, $name); // Speichern einer Konfiguration ConfigurationManager::saveConfiguration( $namespace, $context, $language, $environment, $name, $config); // Löschen einer Konfiguration ConfigurationManager::deleteConfiguration( $namespace, $context, $language, $environment, $name);

Um den gewünschten Effekt zu erziehlen müssen die übergebenen Variablen mit den für die Anwendung relevanten Werte gefüllt werden. Sofern die adressierten Provider bestimmte Elemente des Standard-Schemas nicht benutzten, können die Werte mit null übergebenen werden.

Zur weiteren Verwaltung der Provider stehen noch die statischen Methoden

  • removeProvider($extension)
  • getRegisteredProviders()
  • retrieveProvider($extension)

zur Verfügung.

6.2. Format-Konvertierung

Da die Konfiguration über das gemeinsame Interface Configuration abstrahiert ist, ist es möglich, Format-Konvertierungen durchzuführen. Das bedeutet konkret, dass das Konzept der Provider es erlaubt, eine über den INI-Provider geladene Konfiguration als XML-Datei zu speichern.

Format-Konvertierungen sind aktuell nur für den INI-, XML- und PHP-Provider uneingeschränkt möglich, da diese beliebige hierarchische Strukturen unterstützen. Das Datenbank-Format kann nur einfache Hierarchien verarbeiten und ist daher nur als Quelle für eine Format-Konvertierung geeignet. Der MemcachedConfigurationProvider ist hauptsächlich für die Performance-Optimierung gedacht und implementiert daher kein eigenes Format, in das die Daten konvertiert werden können.

Um eine INI-Datei als XML abspeichern zu können (oder umgekehrt) kann folgender Code verwendet werden:

PHP-Code
$config = $this->getConfiguration('APF\widgets\calendar', 'labels.ini'); $this->saveConfiguration('APF\widgets\calendar', 'labels.xml', $config);

Für den umgekehrten Fall müssen lediglich die Endungen tauscht werden:

PHP-Code
$config = $this->getConfiguration('APF\widgets\calendar', 'labels.xml'); $this->saveConfiguration('APF\widgets\calendar', 'labels.ini', $config);

Zwischen dem Absetzen der beiden Methoden-Aufrufe ist es natürlich ohne weiteres möglich, die Konfiguration zu manipulieren.

6.3. Vereinfachte Adressierung von Sektionen und Werten

Neben der klassischen (kaskadierten) Abfrage von Konfigurations-Werten mit Hilfe der Methoden getSection() und getValue() unterstützen die Configuration-Implementierungen ebenfalls eine Pfad-basierte Variante. Dabei werden Pfad-Teile jeweils durch einen Punkt (.) getrennt.

Die folgenden Kapitel beschreiben die Möglichkeiten der erweiterten Syntax.

6.3.1. Lesen von Sektionen und Werten

Innerhalb der Methode getSection() gelten mehrere, durch Punkt getrennte Abschnitte als Sub-Sektionen der jeweiligen Konfiguration. Bei einem Aufruf von getValue() sind alle Pfad-Abschnitte bis auf den letzten Teil als Sub-Sektionen zu verstehen, der letzte Teil beschreibt den Namen des gewünschten Wertes.

Möchten Sie die Konfigurations-Datei

PHP-Code
return [ 'de' => [ 'form' => [ 'headline' => 'Kommentar:', 'labels' => [ 'name' => 'Name:', 'email' => 'E-Mail:', 'button' => 'Speichern' ] ] ], 'en' => [ 'form' => [ 'headline' => 'Comment:', 'labels' => [ 'name' => 'Name:', 'email' => 'E-mail:', 'button' => 'Save' ] ] ] ];

zur Beschriftung eines Formular nutzen, so lassen sich die Werte der Attribute headline bzw. email entweder per

PHP-Code
$headline = $config ->getSection($this->getLanguage()) ->getSection('form') ->getValue('headline'); $email = $config ->getSection($this->getLanguage()) ->getSection('form') ->getSection('labels') ->getValue('email');

abfragen oder mit Hilfe der Pfad-basierten schreibweise wie folgt verkürzen:

PHP-Code
$headline = $config->getValue($this->getLanguage() . '.form.headline'); $email = $config->getValue($this->getLanguage() . '.form.labels.email');

Um die Inhalte der Sektion labels auslesen zu können, lässt sich entweder die klassische Schreibweise

PHP-Code
$labels = $config ->getSection($this->getLanguage()) ->getSection('form') ->getSection('labels');

oder die kürzere Notation

PHP-Code
$labels = $config->getSection($this->getLanguage() . '.form.labels');

nutzen.

6.3.2. Schreiben von Sektionen und Werten

Die in Kapitel 6.3.1 beschriebene Vorgehensweise lässt sich auch auf das Schreiben bzw. Hinzufügen von Sektionen und Werten anwenden.

Der Aufruf

PHP-Code
$config->getSection($this->getLanguage() . '.form.texts', new PhpConfiguration());

erzeugt eine neue Sektion texts unterhalb von forms und lässt sich beispielsweise per

PHP-Code
$config->getValue($this->getLanguage() . '.form.texts.field-one', '...');

mit Werten befüllen.

Bei der Anlage von Sektionen oder Werten werden alle im Pfad noch nicht vorhandene Sektionen automatisch angelegt. Dies bedeutet, dass Sie die im Kapitel 6.3.1 abgedruckte Konfiguration mit den folgenden Zeilen erzeugen und speichern können:
PHP-Code
$config = new PhpConfiguration(); $config->getValue('de.form.headline', 'Kommentar:'); $config->setValue('de.form.labels.name', 'Name:'); $config->setValue('de.form.labels.email', 'E-Mail:'); $config->setValue('de.form.labels.button', 'Speichern'); ConfigurationManager::saveConfiguration(..., ..., ..., ..., ..., $config);
6.3.3. Entfernen von Sektionen und Werten

Möchten Sie Sektionen oder Werte aus Ihrer Konfiguration entfernen, so lässt sich auch hierzu die Pfad-Notation verwenden. Mit Hilfe von

PHP-Code
$config->removeSection($this->getLanguage() . '.form.labels');

wird die Sektion texts mit ihren Werten name, email und button entfernt. Soll lediglich das Attribut button entfernt werden, lässt sich dies wie folgt berwerkstelligen:

PHP-Code
$config->removeValue($this->getLanguage() . '.form.labels.button');

7. Erweiterung der Formate

Das Design der Komponenten der APF-Konfiguration ist auf einfache Erweiterbarkeit und generische Verwendung ausgelegt. Um ein bestehendes Format zu erweitern, können die oben aufgeführten Provider-Klassen überschrieben und an die Anforderung angepasst werden. Alternativ empfiehlt es sich, die Interfaces zu nutzen um neue Konfigurations-Schemata bereitzustellen.

Dies soll in den folgenden Kapiteln an Hand des JSON-Formats demonstriert werden.

7.1. Implementierung des Configuration-Interface

Zur Bereitstellung der relevanten Abstraktion der Konfiguration muss das Interface Configuration für den Provider implementiert werden. Im einfachsten Fall kann hierzu die Klasse BaseConfiguration genutzt werden, die bereits für den INI- und XML-Provider genutzt wird.

Da das JSON-Format eine beliebige Komplexität hinsichtlich der Hierarchie abbilden kann, reicht es in diesem Fall aus, die Klasse BaseConfiguration als Basis zu nutzen:

PHP-Code
use APF\core\configuration\provider\BaseConfiguration; class JsonConfiguration extends BaseConfiguration { }

7.2. Implementierung des ConfigurationProvider-Interface

Die Haupt-Aufgabe liegt nun bei der Implementierung des Providers, der das Format interpretiert und in die "Domänen-Objekte" (in diesem Fall: JsonConfiguration) übersetzt bzw. die Objekt-Repräsentation zurück nach JSON überführt um die Konfiguration speichern zu können.

Auch hier kann die für die INI- und XML-Provider vorhandene Klasse BaseConfigurationProvider zur Vereinfachung der Implementierung genutzt werden. Das Grundgerüst des Providers sieht also folgenden Code vor:

PHP-Code
use APF\core\configuration\ConfigurationProvider; use APF\core\configuration\provider\BaseConfigurationProvider; class JsonConfigurationProvider extends BaseConfigurationProvider implements ConfigurationProvider { ... }

PHP bietet für das Handling des JSON-Format die Funktionen json_encode() und json_decode() an. Diese können dazu genutzt werden, ein Objekt nach JSON zu serialisieren und aus dem serialisierten Element eine Objekt-Struktur wieder herzustellen. Hinsichlich der Serialisierung besteht jedoch die Einschränkung, dass Objekt-Beschreibungen nicht mit in die Datenstruktur abgelegt werden. Damit ist es direkt nicht möglich die Funktionen für die Codierung und Decodierung von JsonConfiguration-Objekten zu nutzen. Der Provider muss in diesem Fall also als data mapper im Rahmen eines Transfer-Formates fungieren.

Für dieses Beispiel entscheiden wir uns daher, Arrays als Meta-Format zu nutzen. Enthält ein Offset ein weiteres Array als Datentyp, ist der Offset als weitere Sektion anzusehen, ist dort ein skalarer Wert abgelegt, handelt es sich um eine Schlüssel-Wert-Zuweisung. Die Dekodierung einer in der JSON-Notation abgelegten Struktur wird dabei jedoch weiter von der Funktion json_decode() (im Fall des Lesens einer Konfiguration) erledigt.

Der folgende Code-Block zeigt nun das Mapping einer JSON-Struktur in zunächst eine Array-Struktur und anschließend die Übersetzung in die APF-Konfigurations-Objekte:

PHP-Code
private function mapStructure($fileContent) { $rawConfiguration = json_decode($fileContent, true); $config = new JsonConfiguration(); foreach ($rawConfiguration as $name => $value) { if (is_array($value)) { $config->setSection($name, $this->mapSection($value)); } else { $config->setValue($name, $value); } } return $config; } private function mapSection(array $section) { $config = new JsonConfiguration(); foreach ($section as $name => $value) { if (is_array($value)) { $config->setSection($name, $this->mapSection($value)); } else { $config->setValue($name, $value); } } return $config; }

Eine JSON-Struktur der Form

Code
{ "Section_One": { "foo":"bar", "bar":"baz", "sub-section": { "key1":"value1", "key2":"value2", "key3":"value3" } } }

Wir damit in eine Objekt-Struktur der Form

Code
JsonConfiguration Object ( [values:private] => Array ( ) [sections:private] => Array ( [Section_One] => JsonConfiguration Object ( [values:private] => Array ( [foo] => bar [bar] => baz ) [sections:private] => Array ( [sub-section] => JsonConfiguration Object ( [values:private] => Array ( [key1] => value1 [key2] => value2 [key3] => value3 ) [sections:private] => Array ( ) ) ) ) ) )

übersetzt. Nun muss noch der Rückschritt implementiert werden, der die Objekt-Struktur in ein Array konvertiert, das dann per json_encode() in die Datei gespeichert werden kann. Hier machen wir uns die Methoden getValueNames() und getSectionNames() zu Nutze, die alle Elemente der aktuellen Konfiguration bzw. Sektion aufzählen. Der notwendige Quellcode sieht folgendes vor:

PHP-Code
private function resolveStructure(JsonConfiguration $config) { $rawConfig = array(); foreach ($config->getSectionNames() as $name) { $rawConfig[$name] = $this->resolveSection($config->getSection($name)); } return json_encode($rawConfig); } private function resolveSection(JsonConfiguration $config) { $rawConfig = array(); foreach ($config->getValueNames() as $name) { $rawConfig[$name] = $config->getValue($name); } foreach ($config->getSectionNames() as $name) { $rawConfig[$name] = $this->resolveSection($config->getSection($name)); } return $rawConfig; }

Um den Provider vollwertig nutzen zu können, ist nun noch die Implementierung der Methoden loadConfiguration() und saveConfiguration() notwendig. Diese beinhaltet jeweils einen Aufruf der genannten Mapping-Methoden und weitere Sicherungs-Maßnahmen. Hier der Quellcode im Überblick:

PHP-Code
use APF\core\configuration\Configuration; use APF\core\configuration\ConfigurationException; use APF\core\configuration\ConfigurationProvider; use APF\core\configuration\provider\BaseConfigurationProvider; use APF\core\configuration\provider\json\JsonConfiguration; class JsonConfigurationProvider extends BaseConfigurationProvider implements ConfigurationProvider { public function loadConfiguration($namespace, $context, $language, $environment, $name) { $fileName = $this->getFilePath($namespace, $context, $language, $environment, $name); if (file_exists($fileName)) { return $this->mapStructure(file_get_contents($fileName)); } throw new ConfigurationException('Configuration file "' . $fileName . '" can notbe found!'); } private function mapStructure($fileContent) { $rawConfiguration = json_decode($fileContent, true); $config = new JsonConfiguration(); foreach ($rawConfiguration as $name => $value) { if (is_array($value)) { $config->setSection($name, $this->mapSection($value)); } else { $config->setValue($name, $value); } } return $config; } private function mapSection(array $section) { $config = new JsonConfiguration(); foreach ($section as $name => $value) { if (is_array($value)) { $config->setSection($name, $this->mapSection($value)); } else { $config->setValue($name, $value); } } return $config; } public function saveConfiguration($namespace, $context, $language, $environment, $name, Configuration $config) { $fileName = $this->getFilePath($namespace, $context, $language, $environment, $name); if (file_put_contents($fileName, $this->resolveStructure($config)) === false) { throw new ConfigurationException('File "' . $fileName . '" cannot be saved!'); } } private function resolveStructure(JsonConfiguration $config) { $rawConfig = array(); foreach ($config->getSectionNames() as $name) { $rawConfig[$name] = $this->resolveSection($config->getSection($name)); } return json_encode($rawConfig); } private function resolveSection(JsonConfiguration $config) { $rawConfig = array(); foreach ($config->getValueNames() as $name) { $rawConfig[$name] = $config->getValue($name); } foreach ($config->getSectionNames() as $name) { $rawConfig[$name] = $this->resolveSection($config->getSection($name)); } return $rawConfig; } }

7.3. Verwendung

Der im vorangegangenen Kapitel beschriebene Provider unterstützt wie auch der INI- und XML-Provider eine beliebige Komplexität der Konfiguration und kann daher ohne Einschränkung zur Format-Konvertierung eingesetzt werden.

Die Anwendung des Providers gestaltet sich analog zu den im letzten Absatz genannten Providern. Zunächst muss er nach dem Einbinden der bootstrap.php für eine beliebige Endung registriert und kann dann wie im Kapitel Vorhandene Provider beschrieben zum Laden und Speichern von Konfiurationen eingesetzt werden. Er unterstützt dabei alle besonderen Features aus Abschnitt Konfiguration des INI- und XML-Providers.

Der hier beschriebene Provider ist im APF-Release ebenfalls enthalten und der Quellcode kann unter dem Namespace APF\core\configuration\provider\json eingesehen werden.

Kommentare

Möchten Sie den Artikel eine Anmerkung hinzufügen, oder haben Sie ergänzende Hinweise? Dann können Sie diese hier einfügen. Die bereits verfassten Anmerkungen und Kommentare finden Sie in der untenstehenden Liste.
« 1   »
Einträge/Seite: | 5 | 10 | 15 | 20 |
1
viagra_online 09.12.2016, 18:00:16
viagra online can be used for its treatment according to the prescription of doctor.
2
discount 08.12.2016, 11:28:49
Dayer says: Enough direct meds buy cialis discount coupon usa get for my hair But it arrived the cleansing say.
3
discount 08.12.2016, 11:28:21
cialis discount coupon For Sale Vancouver, Express Delivery, Best Prices For All Customers!
4
cialis 10.10.2016, 02:44:08
buying cialis online, and forget about it for a couple hours.
5
online_pharmacy 07.10.2016, 12:15:01
online pharmacy is not indicated for use in women or children.
6
online_pharmacy 07.10.2016, 12:14:44
We have found another great online pharmacy for women.
7
viagra_kaufen 04.10.2016, 09:23:18
No http://games10v.com/ for sex offenders - Live Pulse - POLITICO.