Discussion:
[TYPO3-german] Extbase, Object to array?
Mario T
2017-06-27 07:27:35 UTC
Permalink
Hallo Liste!

ich versuche gerade verzweifelt Objekte (mit Subobjekten, Lazy Loading) zu Arrays zu "konvertieren". Ich habe es mit einer eigenen Funktion versucht:

private function objectToArray($obj)
{
if(is_object($obj)) $obj = (array) $obj;
if(is_array($obj)) {
$new = array();
foreach($obj as $key => $val) {
//$new[$key] = $val;
$new[$key] = $this->objectToArray($val);
}
}
else $new = $obj;
return $new;
}

Allerdings erhalte ich teilweise (je nachdem welche Objekte ich konvertiere) ein memory_limit-Error (obwohl die Objekte nicht groß sind und das memory_limit deutlich höher eingestellt ist).

Wäre hier der TypeConverter die Lösung? Falls ja, wie setze ich den ein?

Was ich eigentlich machen möchte ist ein vorher/nachher-Vergleich (ähnlich wie sysHistory).

Ich danke Euch!
--
LG,
Mario
David BrÃŒnner
2017-06-27 07:58:09 UTC
Permalink
public function queryResultToArray(QueryResult $queryResult, $fields = 'bezeichnung', $addemptyoption = true, $emptyoptionname = '') {
$result = [];
if ($addemptyoption) $result[0] = $emptyoptionname;
while ($queryResult->valid()) {
$obj = $queryResult->current();
if (gettype($fields) == 'array') {
$resultString = '';
foreach ($fields as $field) {
$method = 'get' . ucfirst($field);
if (method_exists($obj, $method)) {
$resultString .= $obj->{$method}() . ', ';
}
}
$result[$obj->getUid()] = substr($resultString, 0, -2);
} else {
$method = 'get' . ucfirst($fields);
if (method_exists($obj, $method)) {
$result[$obj->getUid()] = $obj->{$method}();
}
}
$queryResult->next();
}
return $result;
}
Mario T
2017-06-27 08:20:14 UTC
Permalink
Hallo nochmal!

Danke für die Funktion, aber was genau kann ich damit machen? Aktuell erhalte ich ein "....must be an instance of VENDOR\EXT\Controller\Bla, instance of VENDOR\EXT\Domain\Model\Bla given, called in...."

Ich habe aktuell zwei Objekte:

$current = $this->BlaRepository->findByUid(1);
$updated = $blaObject;

Ich weiß jeweils nicht welche Felder geändert werden und muss diese später in einer foreach-Schleife vergleichen. Das funktioniert auch bereits. Allerdings erhalte ich mit meiner aktuellen Funktion (s. 1. Post) ein memory_limit-Error.

Wie bekomme ich die Objekte in $current und $updated nun zu Arrays?

Danke nochmal!
--
LG,
Mario
g***@tonarchiv.ch
2017-06-27 11:59:49 UTC
Permalink
Die Klasse QueryResults - oder wie die auch immer konkret heißt - hat
doch bereits eine Methode toArray()...

Vermutlich verstehe ich das Problem nicht.
Post by Mario T
Hallo nochmal!
Danke für die Funktion, aber was genau kann ich damit machen? Aktuell
erhalte ich ein "....must be an instance of VENDOR\EXT\Controller\Bla,
instance of VENDOR\EXT\Domain\Model\Bla given, called in...."
$current = $this->BlaRepository->findByUid(1);
$updated = $blaObject;
Ich weiß jeweils nicht welche Felder geändert werden und muss diese
später in einer foreach-Schleife vergleichen. Das funktioniert auch
bereits. Allerdings erhalte ich mit meiner aktuellen Funktion (s. 1.
Post) ein memory_limit-Error.
Wie bekomme ich die Objekte in $current und $updated nun zu Arrays?
Danke nochmal!
Mario T
2017-06-27 15:21:39 UTC
Permalink
Stimmt. Diese habe ich jetzt auch gefunden. Aber...

Allerdings funktioniert das nur bei findAll() bzw. bei einer Liste von Objekten. Suche ich einen Datensatz mit findByUid()->toArray() kommt: Call to undefined method VENDOR\EXT\Domain\Model\Bla::toArray()

Hinzu kommt leider auch das die Unterobjekte weiterhin Objekte bleiben. Ich bräuchte jedoch das vollständige Objekt inkl. Kind-Objekte als Array.
--
LG,
Mario
g***@tonarchiv.ch
2017-06-27 16:26:10 UTC
Permalink
findByUid liefert ja auch nur ein einziges objekt per definition. daher
kannst du daraus auch kein array bauen...
Post by Mario T
Stimmt. Diese habe ich jetzt auch gefunden. Aber...
Allerdings funktioniert das nur bei findAll() bzw. bei einer Liste von
Call to undefined method VENDOR\EXT\Domain\Model\Bla::toArray()
Hinzu kommt leider auch das die Unterobjekte weiterhin Objekte
bleiben. Ich bräuchte jedoch das vollständige Objekt inkl.
Kind-Objekte als Array.
Dr. Dieter Porth
2017-06-27 17:51:10 UTC
Permalink
Sorry.

Hatte den nachfolgenden Thread im Mailprogramm übersehen.
Post by g***@tonarchiv.ch
findByUid liefert ja auch nur ein einziges objekt per definition. daher
kannst du daraus auch kein array bauen...
Post by Mario T
Stimmt. Diese habe ich jetzt auch gefunden. Aber...
Allerdings funktioniert das nur bei findAll() bzw. bei einer Liste von
Call to undefined method VENDOR\EXT\Domain\Model\Bla::toArray()
Hinzu kommt leider auch das die Unterobjekte weiterhin Objekte
bleiben. Ich bräuchte jedoch das vollständige Objekt inkl.
Kind-Objekte als Array.
Ich möchte eine IDE wie phpstorm bei der Entwicklung nicht mehr missen,
da man bei geeigneter Einstellung und sorgfältiger Nutzung der
Annotationen immer angezeigt bekommt, welche Methoden man verfügbar hat.
Fehler wie "Call to undefined method" werden dadurch vermeidbar.

Mit Bezug auf meinen vorherigen Thread. Wenn du unbedingt alles als
Array braucht, dann iteriere die Kindelelement, nachdem du sie dir mit
einem Getter geholt hast. Technisch ist ein solche Ummappen so manches
Mal ein Indiz dafür, dass dein Modell schlecht zu den Anforderungen
passt oder dass sich die Anforderungen merklich geändert haben.

Mit besten Grüßen
Dieter
--
----
Dr. Dieter Porth - Web-Entwickler
Mario T
2017-06-28 07:06:11 UTC
Permalink
Hallo Dieter,

vielen Dank für deine ausführlichen Antworten! Ich werde mir deine Ratschläge zu Herzen nehmen..

Eigentlich funktioniert die ganze Anwendung problemlos. Ich suche nur "verzweifelt" nach einer Lösung welche mir eine Art sys_history meiner Extbase-Erweiterung generiert. Mit kleineren Objekten gibt es hier auch kein Problem. Nur wenn es dann zu viele Kindobjekte werden.

Grüße,
Mario
--
LG,
Mario
Dieter Porth
2017-06-29 18:09:49 UTC
Permalink
Hallo Mario,
Post by Mario T
Eigentlich funktioniert die ganze Anwendung problemlos. Ich suche nur "verzweifelt" nach einer Lösung welche mir eine
Art sys_history meiner Extbase-Erweiterung generiert. Mit kleineren Objekten gibt es hier auch kein Problem. Nur wenn
es dann zu viele Kindobjekte werden.
Du brauchst also einen Dump von einem Datenbank-Objekt, dass hoch-relational verknüpft ist. Ich habe da keine Lösung.

Ich habe mich vor einiger Zeit angefangen, über das Problem nachzudenken. Meine Comic-Extension produziert Comic-Objekte als Content-Elemente, die ihre Informationen über mehr als 10 Tabellen verteilen. Ich weiß bisher nicht, wie man einfach einen Comic von einem TYPO3-System auf ein anderes System kopiert.

Wenn du eine einfache Idee findest, werde ich mich über einen Hinweis freuen.

Mit besten Grüßen
Dieter
Mario T
2017-07-06 08:22:04 UTC
Permalink
Also ich habe sozusagen zwei Fliegen mit einer Klappe geschlagen:

1. Individuelle Model-Validierung (inspiriert von http://blog.teamgeist-medien.de - "Dynamische Validierung von Models je nach Formularauswahl")
2. Vergleich bestimmter Properties (eine Art sys_history für eigene Extensions mit Änderungen über das Frontend)

Ich versuche mal kurz meine Lösung aufzuzeigen:

Zu #1:
Gehen wir davon aus ich habe ein Model "MyUser" (extends feuser) - In diesem Model werden alle getter und setter sowie Variablen-Deklaration OHNE jegliche Validierung (außer es wird von einem bestimmten Feld immer eine Validierung benötigt) gesetzt.

Für die Registrierung habe ich ein Model "MyUserCreate" (extends MyUser). Hier setze ich nur noch die Variablen-Deklarationen MIT meinen Validierungen welche ich bei der Registrierung benötige (z.B. Username, Email, FirstName, LastName, etc.)

Für, zum Beispiel, ein Profil-Update habe ich ein Model "MyUserUpdate" (extends MyUser). Da der Nutzer zum Beispiel nur noch seine E-Mail Adresse und seinen Vornamen ändern kann setze ich in diesem Model nur noch eine Variablen-Deklaration MIT Validierung für email und firstName.

Zu #2:
Zusätzlich habe ich folgendes gemacht:
- Da ich eh für einzelne Aktionen (leider) einzelne Models setze (sofern nötig!) setze ich dort auch gleich eine Variable/Array mit $fieldlist - Bei einem Profilupdate könnte das zum Beispiel "email, first_name" sein. Beim Update des Datensatzes hole ich mir das aktuelle Objekt und das "zukünftige Objekt" und vergleiche ausschließlich die in $fieldlist angegebenen Properties. Leider etwas umständlich aber man könnte auch in dem "MyUser" Model bereits ein "Standard-Set" an Werten angeben welche verglichen werden sollen.

- In dem Model "MyUser" habe ich eine zusätzliche Variable (+setter) gesetzt mit "tableName = 'fe_users';" - Dies ermöglicht mir beim späteren Vergleich (vorher/nachher) bzw. beim Schreiben in die DB zusätzlich zur RecUid, fieldlist und historyData auch den TableName zu setzen (sofern man unterschiedliche Tabellen/Objekte) in einer allgemeinen Logging-Tabelle ablegen möchte.

Ich hoffe ich konnte das einigermaßen korrekt rüber bringen. Vielleicht gibt es hier und da etwas zu verbessern?
--
LG,
Mario
Dr. Dieter Porth
2017-06-27 17:38:23 UTC
Permalink
Hallo Mario,

Leider enthält dein Code-Snippet keine wesentlichen Informationen,
sondern du versucht das nachzubauen, was TYPO3 nativ tut.

Du hast also eine Abfrage mit dem Repository gemacht und möchtest das
Ergebnis iterieren, zumindest vermute ich dies

Normalerweise kann du die Suchergebnisse direkt iterieren, ohne sie
vorab explizit zu konvertieren. Wenn es dann aber sein muss, solltest
die toArray()-Methode beim Query-Aufruf im Repository verwenden. Dann
kümmert sich TYPO3 um den Rest - zumindest auf der ersten Ebene.

Die Lazy-Annotation kann manchmal Schwierigkeiten machen, weil plötzlich
die Objektklassen nicht zur Verfügung stehen und damit entsprechende
Klassen fehlen. Ich optimiere meist erst nachträglich mit @lazy.

P.S. Ich persönlich habe die Magie von @lazy nicht wirklich verstanden
und bin schon zwei Mal auf die Nase gefallen, weil TYPO3 lieber lazy
blieb statt eine spät benötigte Klasse noch nachzuladen.

Mit besten Grüßen

Dieter

.
Post by Mario T
Hallo Liste!
ich versuche gerade verzweifelt Objekte (mit Subobjekten, Lazy
Loading) zu Arrays zu "konvertieren". Ich habe es mit einer eigenen
private function objectToArray($obj)
{
if(is_object($obj)) $obj = (array) $obj;
if(is_array($obj)) {
$new = array();
foreach($obj as $key => $val) {
//$new[$key] = $val;
$new[$key] = $this->objectToArray($val);
}
}
else $new = $obj;
return $new;
}
Allerdings erhalte ich teilweise (je nachdem welche Objekte ich
konvertiere) ein memory_limit-Error (obwohl die Objekte nicht groß
sind und das memory_limit deutlich höher eingestellt ist).
Wäre hier der TypeConverter die Lösung? Falls ja, wie setze ich den ein?
Was ich eigentlich machen möchte ist ein vorher/nachher-Vergleich
(ähnlich wie sysHistory).
Ich danke Euch!
--
----
Dr. Dieter Porth - Web-Entwickler
Loading...