Vorgestellt und diskutiert werden soll das Konzept einer PHP-Klasse für die Selection und Sortierung für mehrdimensionale Arrays mit Tabellenstrukturen. Nützlich kann eine solche Klasse bei der Verarbeitung von Daten sein welche z.B. als JSON aus einer API(Webservice) oder als CSV daherkommen. Mit tabellenartigen Datenstrukturen sind Arrays ähnlich wie dies hier gemeint:
Bei der Notation der Methoden fällt sofort die Ähnlichkeit zu SQL auf.
Das ist beabsichtigt. Die Funktionsweise ist jedoch schon etwas anders. Beispiel select-Methode.
Die mit Komma getrennten Ausdrücke werden nacheinander abgearbeitet. Ein alleinstehender Feldname(Schlüssel) wird nur für einen Abruf der Daten mit FetchAll() vorgemerkt. Ein Ausdruck mit AS erzeugt intern eine neue Spalte. Diese neue Spalte steht "sofort" für nachfolgende Ausdrücke im select oder nachfolgende Methoden zur Verfügung. Durch die Nutzung von Funktionen für select und orderBy wird die Klasse extrem vielseitig. Die obige FORMAT-Funktion entspricht der sprintf-Funktion von PHP.
Folgende Funktionen sind aktuell verfügbar:
UPPER, LOWER, TRIM, FORMAT, DATEFORMAT, REPLACE, SUBSTR, LIKE, INTVAL, FLOATVAL
Ist keine dieser Funktionen für den konkreten Anwendungsfall nutzbar, können eigene Funktionen mit der Methode addSqlFunction der Klasse bekannt gemacht und benutzt werden.
Diese Funktionen sind alle auch für die Methode orderBy nutzbar.
Eine Vergleichsfunktion wie bei usort muss vom Nutzer nicht erstellt werden, diese wird in der Klasse dynamisch aus dem Sortierausdruck erstellt. Damit wird das Sortieren eines Arrays mit mehreren Kriterien stark vereinfacht.
Das jetzige Konzept verlangt für jede Tabellenzeile einen gleiche Struktur. Leider wird das in der Praxis von den Datenlieferanten nicht immer eingehalten.
Die Frage wie damit umgegangen werden soll, wenn beispielsweise ein Feldelement fehlt, ist noch ein offenes Problem.
Die Feldelemente können selbst wieder Arrays, Objekte oder ein Gemisch aus Arrays und Objekten der StdClass sein. Typisch sind da solche Strukturen
wenn die Daten aus einer XML kommen. Um Zugriff auf untere Ebenen zu haben gibt es 2 Methoden um die Daten unterhalb der 2.Ebene zu "flatten".
Mit
wird das Array in der 2.Ebene flach gemacht. Das Resultat
Mit der Methode addFlatKeys() bleiben die tieferen Strukturen erhalten und die flachen Elemente werden zugefügt. Dieses Konzept erscheint für mich als ein gangbarer Weg tiefe Strukturen zu verarbeiten und gleichzeitig den Aufwand des internen Parsers für select und orderBy klein zu halten.
Die einzelnen Methoden sind auch mehrfach nutzbar. Sortierungen wie die ältesten 5 Mitglieder zu ermitteln und diese dann den Namen nach sortiert auszugeben stellt auch kein Problem dar.
Zum Schluss möchte ich noch etwas klarstellen:
Die Klasse ist nicht dafür gedacht Daten roh aus einer Datenbank zu holen um diese dann zu Filtern und zu Sortieren. Das kann mit einer Datenbank besser und schneller erledigt werden. Auch bei größeren Datenmengen (>1000 Datensätze) und wenn diese nicht sofort verarbeitet werden ist abzuwägen, ob es nicht Sinn macht die Daten in eine Datenbank zu bringen.
LG jspit
PHP-Code:
$data = [
['id' => 1, 'val' => 23.333333333],
['id' => 2, 'val' => 13.7777777777],
];
PHP-Code:
$newData = tableArray::create($data)
->select('id, FORMAT("%6.2f",val) AS rval')
->orderBy('val ASC')
->fetchAll();
Die mit Komma getrennten Ausdrücke werden nacheinander abgearbeitet. Ein alleinstehender Feldname(Schlüssel) wird nur für einen Abruf der Daten mit FetchAll() vorgemerkt. Ein Ausdruck mit AS erzeugt intern eine neue Spalte. Diese neue Spalte steht "sofort" für nachfolgende Ausdrücke im select oder nachfolgende Methoden zur Verfügung. Durch die Nutzung von Funktionen für select und orderBy wird die Klasse extrem vielseitig. Die obige FORMAT-Funktion entspricht der sprintf-Funktion von PHP.
Folgende Funktionen sind aktuell verfügbar:
UPPER, LOWER, TRIM, FORMAT, DATEFORMAT, REPLACE, SUBSTR, LIKE, INTVAL, FLOATVAL
Ist keine dieser Funktionen für den konkreten Anwendungsfall nutzbar, können eigene Funktionen mit der Methode addSqlFunction der Klasse bekannt gemacht und benutzt werden.
PHP-Code:
$newData = tableArray::create($data)
->addSqlFunction('mul',function($v1,$v2){return $v1*$v2;})
->select('id,val,factor,mul(val,factor) as product')
->fetchAll();
PHP-Code:
->orderBy("LIKE(pos,'%CEO%') DESC, pos ASC, name")
Das jetzige Konzept verlangt für jede Tabellenzeile einen gleiche Struktur. Leider wird das in der Praxis von den Datenlieferanten nicht immer eingehalten.
Die Frage wie damit umgegangen werden soll, wenn beispielsweise ein Feldelement fehlt, ist noch ein offenes Problem.
Die Feldelemente können selbst wieder Arrays, Objekte oder ein Gemisch aus Arrays und Objekten der StdClass sein. Typisch sind da solche Strukturen
PHP-Code:
$data = [
['id' => 1, '@attributes' => ['currency' => "USD",'rate' => "1.1370"]],
['id' => 2, '@attributes' => ['currency' => "JPY",'rate' => "1.28"]],
];
Mit
PHP-Code:
->flatten()
PHP-Code:
$newData = [
['id' => 1, '@attributes.currency' => "USD", '@attributes.rate' => "1.1370"],
['id' => 2, '@attributes.currency' => "JPY", '@attributes.rate' => "1.28",]
];
Die einzelnen Methoden sind auch mehrfach nutzbar. Sortierungen wie die ältesten 5 Mitglieder zu ermitteln und diese dann den Namen nach sortiert auszugeben stellt auch kein Problem dar.
PHP-Code:
->orderBy('alter DESC')
->limit(5)
->orderBy('name ASC')
Die Klasse ist nicht dafür gedacht Daten roh aus einer Datenbank zu holen um diese dann zu Filtern und zu Sortieren. Das kann mit einer Datenbank besser und schneller erledigt werden. Auch bei größeren Datenmengen (>1000 Datensätze) und wenn diese nicht sofort verarbeitet werden ist abzuwägen, ob es nicht Sinn macht die Daten in eine Datenbank zu bringen.
LG jspit
Kommentar