Bei dieser Software handelt es sich um eine Erweiterung für das Open Source CMS Contao. Die Software stellt zwei Collections zur Verfügung und ist als Ersatz für den Einsatz für Arrays gedacht.
Patrick Froch hallo@patrick-froch.de
Die Software wird unter LGPL-v3 veröffentlicht. Details sind in der Datei LICENSE zu finden.
- php: ^8.1
- contao/core-bundle:^5.0
- patrickfroch/databaselayer: ^1.0
- patrickfroch/valueobjects: ^2.0
Die Installation geschieht über den ContaoManager. Einfach nach esit/datacollections suchen und installieren.
Aleternativ kann die Erweiterung mit folgendem Befehl über Composer installiert werden:
composer require esit/datacollectionsDie Erweiterung wurde erfolgreich mit folgenden Kombinationen aus PHP und Contao getestet:
| Contao | ||||
|---|---|---|---|---|
| ✓ | ✓ | ✓ | ✓ | |
| ✓ | ✓ | ✓ | ✓ | |
| ✓ | ✓ | ✓ | ✓ | |
| ✓ | ✓ | ✓ | ✓ | |
| ✓ | ✓ | ✓ | ✓ | |
| ✓ | ✓ | ✓ | ✓ |
Die NameInterfaces sind für die Verwendung der DatabaseRowCollction erforderlich. Damit sichergestellt ist, dass es
sich um valide Namen für Tabellen und Felder handelt, werden ValueObjects verwendet.
Es muss eine Aufzählung (Enumeration) mit den Tabellennamen und je eine pro Tabelle mit den Feldnamen erstellt werden.
Die Aufzählung, die das TablenamesInterface implementiert, enthält die Namen aller relevanten Tabellen im Projekt.
use Esit\Valueobjects\Classes\Database\Enums\TablenamesInterface;
enum Tablenames implements TablenamesInterface
{
case tl_content;
case tl_test_data;
}Die Aufzählungen, die das FieldnamesInterface implementieren, enthalten die Namen aller Felder einer Tabelle. Es
muss für jede Tabelle eine Aufzählung mit den entsprechenden Feldern geben.
use Esit\Valueobjects\Classes\Database\Enums\FieldnamesInterface;
enum TlContent implements FieldnamesInterface
{
case id;
case tstamp;
case headline;
}
enum TlTestData implements FieldnamesInterface
{
case id;
case tstamp;
case specialdata;
}Alle Collections erweitern die Doctrine\Common\Collections\ArrayCollection
und bietet so auch alle Funktionen aus Doctrine\Common\Collections\ArrayCollection.
Im Einzelnen sind dies die folgenden Methoden:
- add
- clear
- contains
- containsKey
- current
get=> DurchgetValueersetzt, um die gleichen Methodennamen in allen Collections verwenden zu können.- getKeys
- getValues
- isEmpty
- first
- exists
- findFirst
- filter
- forAll
- indexOf
- key
- last
- map
- reduce
- next
- partition
- remove
- removeElement
set=> DurchgetValueersetzt, um die gleichen Methodennamen in allen Collections verwenden zu können.- slice
- toArray
- matching
Die ArrayCollection ist für den direkten Ersatz von Arrays gedacht. Die Collection kann
beliebige Werte aufnehmen und bietet viele Methoden für den Umgang mit Arrays.
Die DatabaseRowCollection ist eine Spezialform der ArrayCollection. Sie bietet ebenfalls
viele Methoden für den Umgang mit Arrays. Ihr Zweck ist es, eine Tabellenzeile aufzunehmen.
Die Tabellenzeile kann mit save() gespeichert werden. Des Weiteren bietet sie ein LazyLoading
von abhängigen Daten, wenn dies im DCA konfiguriert wurde.
Für die Erstellung der Collections gibt es eine Factory. Sie kann eine ArrayCollection, eine
DatabaseRowCollection und eine ArrayCollection mit mehreren DatabaseRowCollections erstellen.
Hier wird die Erstellung und einige Methoden der ArrayCollection gezeigt:
use Esit\Datacollections\Classes\Services\Factories\CollectionFactory;
class MyClass
{
public function __construct(private readonly CollectionFactory $factory)
{
}
public function useArray(): void
{
$myArrayCollection = $this->factory->createArrayCollection(
['t1' =>'test01', 't2' => 'test02']
);
// getValue
echo $myArrayCollection->getValue('t1'); // => test01
// setValue
$myArrayCollection->setValue('t3', 'Test03');
// fetchData
$data = $myArrayCollection->fetchData(); // => ['t1' =>'test01', 't2' => 'test02', 't3' => 'Test03']
// Iterator
foreach ($myArrayCollection as $k => $v) {
echo "$k: $y";
}
}
}Für die Verwendung der DatabaseRowCollection werden zunächst Enumerations vom Typ TablenamesInterface und
FieldnamesInterface benötigt (s.o.). Mit diesen können dann über die Factory die DatabaseRowCollections erstellt
werden. Da intern ValueObjects für die Namen der Tabellen und Felder verwendet werden, können nur DatabaseRowCollection
für existierende Tabellen erstellt werden und nur auf darin wirklich enthaltene Felder zugegriffen werden.
use Esit\Datacollections\Classes\Services\Factories\CollectionFactory;
class MyClass
{
public function __construct(private readonly CollectionFactory $factory)
{
}
public function useDatabaseRow(): void
{
// Eine leere Collection erstellen
$myDbCollection = $this->factory->createDatabaseRowCollection(
Tablenames::tl_test_data,
[] // Hier können Daten als Array oder ArrayCollection übergeben werden.
);
// setValue
$myDbCollection->getValue(TlTestData::specialdata, 'TestValue');
// getValue
echo $myDbCollection->getValue(TlTestData::specialdata); // => 'TestValue'
// fetchData
$data = $myDbCollection->fetchData(); // Alle Daten der Tabellenzeile als Array
// ArrayCollection mit mehreren DatabaseRowCollections erstellen.
$myCollections = $this->factory->createMultiDatabaseRowCollection(
Tablenames::tl_test_data,
[] // Hier können Daten als multidemensionales Array übergeben werden.
);
// Iterator ($myCollections ist eine ArrayCollection, $oneDbCollection je eine DatabaseRowCollection)
foreach ($myCollections as $oneDbCollection) {
var_dump($oneDbCollection); // oder alle anderen Aktionen einer DatabaseRowCollection
}
}
}Für den Zugriff auf einen Wert wird immer ein FieldnamesInterface benötigt.
Auf den DatabaseRowCollection stehen die gleichen Methoden zur Verfügung, wie auf den ArrayCollection. Zusätzlich
gibt es die Methode save um den Datensatz zu speichern.
Arrays werden immmer als serialisierter String abgelegt und als ArrayCollection zurückgegeben.
Wenn im DCA das LazyLoading konfiguriert ist, werden die abhängigen Daten automatisch beim Zugriff auf das Feld geladen und zurückgegeben.
Damit die abhängigen Daten geladen werden können, muss das LazyLoading im DCA konfiguriert werden.
$table = 'tl_test_data';
$GLOBALS['TL_DCA'][$table]['fields']['author'] = [
'label' => &$GLOBALS['TL_LANG'][$table]['author'],
'exclude' => true,
'inputType' => 'text',
'foreignKey' => 'tl_member.CONCAT(firstname,' ',lastname)',
'lazyloading' => ['table'=>'tl_member', 'field'=>'id', 'serialised'=>false],
'eval' => ['mandatory'=>true, 'maxlength'=>255],
'sql' => "varchar(255) NOT NULL default ''"
];table gibt die Tabelle an, aus der die Daten geladen werden sollen. field gibt an, in welchem Feld der Fremdtabelle
der Wert gesucht wird und serialised gibt an, ob es sich um einen Werte (false) oder ein serialisiertes Array
von Werten handelt (true).
Die DatabaseRowCollection kann zusätzliche Daten verwalten, die nicht in der Datenbank gespeichert werden können.
Die ist nützlich, wenn man den Daten für die Ausgabe zusätzliche Werte mitgeben will.
Es gibt zu diesem Zweck eine extra Collection, in der die zusätzlichen Daten abgelegt werden. Mit den folgenden Methoden kann darauf zugegriffen werden.
use Esit\Datacollections\Classes\Services\Factories\CollectionFactory;
class MyClass
{
public function __construct(private readonly CollectionFactory $factory)
{
}
public function useDatabaseRow(): void
{
// Eine leere Collection erstellen
$myDbCollection = $this->factory->createDatabaseRowCollection(
Tablenames::tl_test_data,
[] // Hier können Daten als Array oder ArrayCollection übergeben werden.
);
// Zusätzlichen Wert berechnen und hinterlegen
$myDbCollection->setCommonValue('incremented_id', $myDbCollection->getValue('id') + 1);
// Zusätzlichen Wert abfragen
echo $myDbCollection->getCommonValue('incremented_id'); // => id + 1
// Alle zusätzlichen Werte als Array beziehen
$commonData = $myDbCollection->getCommonDataAsArray(); // ['incremented_id' => id + 1]
}
}