Zum Hauptinhalt gehen

Datenbankabfrage aus einer Vorlage heraus

Kommentare

7 Kommentare

  • Zendesk API User
    Author: neumann - 11/9/2017 14:32

    Hallo Fabian

    Grundsätzlich liegst du schon richtig darin, dass du Abfragen im CMS_HEADER machen kannst. Siehe dazu auch

    http://www.e-spirit.com/odfs52/vorlagenentwick/vorlagensyntax/datenbank-abfra/

    Ich verstehe leider nicht genau wo es bei dir hapert. Geht es bei deiner Frage darum wie man dann in der HTML-Vorlage auf die Ergebnisse der Abfrage aus dem Header zugreift?

    Viele Grüße

    Emre

    0
  • Zendesk API User
    Author: FabsH - 11/20/2017 9:12

    Hallo Emre,

    erstmal vielen Dank für deine Antwort. Dadurch bin ich schon mal ein gutes Stück weiter gekommen.

    Mein Script sieht jetzt wie folgt aus:

    //!Beanshell

    import de.espirit.firstspirit.access.store.Store;

    import de.espirit.firstspirit.access.store.Store.Type;

    import de.espirit.firstspirit.access.store.templatestore.Query;

    import de.espirit.firstspirit.access.store.templatestore.Schema;

    import de.espirit.firstspirit.agency.SpecialistsBroker;

    import de.espirit.firstspirit.agency.StoreAgent;

    import de.espirit.firstspirit.service.value.ValueService;

    import de.espirit.or.EntityList;

    import de.espirit.or.Session;

    import de.espirit.or.schema.Entity;

    import de.espirit.or.query.*;

    StoreAgent storeAgent = context.requireSpecialist(StoreAgent.TYPE);

    Store store = storeAgent.getStore(Type.TEMPLATESTORE);

    Schema schema = store.getSchemes().getSchemaByName("fabian");

    Session session = schema.getSession();

    Select select = session.createSelect("divisions");

    EntityList entityList = session.executeQuery(select);

    return(entityList);

    Somit erhalte ich wie gewünscht alle Einträge aus der Tabelle

    In meiner Vorlage führe ich das Script mittels CMS_RENDER aus. Doof ist nur, dass CMS_RENDER ja immer ein Object vom Typ de.espirit.firstspirit.parser.impl.TemplateDocumentImpl zurückgibt. Bedeutet ja für mich, dass ich das Ergebnis meines Scripts nicht mit einer for-Schleife durchlaufen kann.

    Kann ich also das Abfrageergebnis irgendwie in eine Liste übertragen? Im ODFS wird ein Beispiel genannt, wie eine Liste erzeugt wird:

    $CMS_SET(myList, [])$

    $CMS_SET(void, myList.add("1.Eintrag"))$

    Für meinen Fall müsste ich also etwas in dieser Richtung nutzen (wenn es das gibt) um die "Umwandlung" durch CMS_RENDER in ein TemplateDocument zu umgehen:

    $CMS_SET(divisions, script:"mein_abfrag_script")$

    Geht das irgendwie?

    Danke!

    0
  • Zendesk API User
    Author: mbergmann - 11/20/2017 9:42

    Hallo Fabian,

    zum Thema "Rückgabe aus einem Script" schau einfach mal hier.

    Allerdings: An die Einträge der Tabelle kommst Du auch ganz ohne Skript, eben per ContentSelect. Und Dein Skript berücksichtigt übrigens auch nicht den Freigabestand, d.h. Du gibst immer den Current stand aus - auch bei einer Generierung.

    Ich würde das mit einem normalen ContentSelect lösen.

    Viele Grüße

    Michael

    0
  • Zendesk API User
    Author: FabsH - 11/20/2017 10:10

    Hallo Michael,

    der Hinweis auf contentSelect ist natürlich richtig. Das ist ein Ansatz den ich ebenfalls verfolge. Und gerade mit der Freigabegeschichte ist das natürlich so eine Sache.

    In Sachen ContentSelect gehe ich bisher den Weg, dass ich eine Formatvorlage erstellt habe, welche im Header die Abfrage mittels ContentSelect tätigt. Nach dem Header schreibe ich die Daten in eine Liste:

    $CMS_SET(divisions, [])$

    $CMS_FOR(x, mod_divisions)$

        $CMS_SET(void, divisions.add(x))$

    $CMS_END_FOR$

    $CMS_VALUE(divisions)$

    In meiner Absatzvorlage greife ich wie folgt darauf zu:

    $CMS_SET(set_divisions)$

        $CMS_RENDER(template:"previewoverlay_divisions_query", resultContainer:set_divisions)$

    $CMS_END_SET$

    Das Ergebnis ist nur leider dasselbe wie bei der Script-Variante. Ich bekomme ein Objekt des Typ TemplateDocumentImpl zurück.

    Ein Gedanke von mir war, die Ausgabe komplett in der Formatvorlage zu gestalten. Dagegen spricht aber, dass ich das Abfrageergebnis in verschiedenen Absatzvorlagen benutzen will/muss und die HTML-Ausgabe jedesmal anders aussieht.

    Wie schaffe ich es also, dass ich das Ergebnis meiner Datenbankabfrage aus der Formatvorlage in einer Liste in meiner Absatzvorlage verwenden kann? Leider bin ich weder hier im Forum noch im ODFS fündig geworden.

    Vielen Dank schon mal mbergmann

    Fabian

    0
  • Zendesk API User
    Author: mbergmann - 11/20/2017 10:33

    Hallo Fabian,

    Dein Problem ist erstmal, dass das "mehrteilige" CMS_SET (also das mit CMS_END_SET) keinen String o.ä. erzeugt sondern eben ein TemplateDocument. Das kann man sich als eine Art Funktion vorstellen, die auch tatsächlich erst beim Aufruf (und zwar bei jedem Aufruf) entsprechend des jeweils geltenden Variablenkontextes ausgewertet wird. Letztlich passt das nicht zu Deinem Anwendungsfall.

    Bei Dir passen die ganzen Namen irgendwie nicht zusammen. Du musst die Liste schon von "außen" - also beim Rendertemplate-Aufruf - reingeben und nicht erst im Rendertemplate definieren. Der Aufruf eines Rendertemplates erzeugt einen eigenen Scope - auf Variablen, die erst dort definiert werden, hast Du dann im Absatztemplate keinen Zugriff.

    Ganz grob sollte es ungefähr so aussehen:

    Im Absatztemplate:

    $CMS_SET(set_divisions,[])$

    $CMS_RENDER(template:"previewoverlay_divisions_query", resultContainer:set_divisions)$

    $CMS_FOR(for_divisionEntry, set_divisions)$

      ...

      $CMS_VALUE(for_divisionEntry.SPALTENNAME)$

      ...

    $CMS_END_FOR$

    Im Rendertemplate:

    <CMS_HEADER>

      <CMF_FUNCTION name="contentSelect" resultname="fr_divisions">

      ...

      </CMS_FUNCTION>

    </CMS_HEADER>

    $CMS_FOR(for_entry,fr_divisions)$

      $CMS_SET(void, resultContainer.add(for_entry))$

    $CMS_END_FOR$

    Anmerkung: Das führt dazu, dass die DB-Einträge im Speicher landen. Wenn es nur wenige sind, ist das OK.

    Viele Grüße

    Michael

    0
  • Zendesk API User
    Author: mbergmann - 11/20/2017 11:02

    Hallo Fabian,

    alternativ könntest Du auch folgendes versuchen:

    Im Absatztemplate:

    $CMS_SET(set_divisionResultContainer,[])$

    $CMS_RENDER(template:"previewoverlay_divisions_query", resultContainer:set_divisionResultContainer)$

    $CMS_SET(set_divisions, set_divisionResultContainer.first)$

    $CMS_FOR(for_divisionEntry, set_divisions)$

      ...

      $CMS_VALUE(for_divisionEntry.SPALTENNAME)$

      ...

    $CMS_END_FOR$

    Im Rendertemplate:

    <CMS_HEADER>

      <CMF_FUNCTION name="contentSelect" resultname="fr_divisions">

      ...

      </CMS_FUNCTION>

    </CMS_HEADER>

    $CMS_SET(void, resultContainer.add(fr_divisions))$

    Der Unterschied ist hier, dass die einzelnen Einträge nicht erst alle in den Speicher gepackt werden - ein ContentSelect arbeitet nämlich "lazy". Stattdessen gibst Du einfach das Listable zurück. Auch hier brauchst Du einen Container, in den der Wert hineingelegt wird. In diesem Fall enthält er nach dem CMS_RENDER-Aufruf allerdings nur ein Element (eben das Listable).

    Habe ich in der Form allerdings noch nicht ausprobiert.

    Eine weitere Variante wäre grundsätzlich - vor allem wenn Du es öfter brauchst und es eher wenige Datensätze sind - die Abfrage im Ausgabekanal des Projekteinstellungs-Templates zu machen. Der wird nämlich einmal zu Beginn jeder Generierung (allerdings auch bei jeder Preview-Anforderung) ausgewertet, die dort definierten Variablen stehen dann im root-Kontext zur Verfügung.

    Viele Grüße

    Michael

    0
  • Zendesk API User
    Author: FabsH - 11/20/2017 12:35

    mbergmann​, ich danke dir! Du hast meinen Tag gerettet :smileyhappy:

    0

Bitte melden Sie sich an, um einen Kommentar zu hinterlassen.