Contao-Camp 2024
Ergebnis 1 bis 24 von 24

Thema: Inhalte eines DCA-Feldes auszählen und ans FE übergeben

  1. #1
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard Inhalte eines DCA-Feldes auszählen und ans FE übergeben

    Guten Morgen,

    ich habe mittels DCA die tl_news um ein Feld "Stufe" erweitert. Das klappt auch soweit.

    Jetz würde ich gerne im FE auszählen, wie oft eine geweilige Stufe vorkommt im ausgewählten Jahr.

    Als SQL würde es so aussehen:

    Code:
    SELECT COUNT(id) FROM `tl_news` WHERE `tl_news`.`einsatzkat` LIKE "B%" AND year(from_unixtime(date)) = 2020
    Wobei das Jahr abhängig sein soll von der Auswahl des Jahres in News-Archive-Menü

    Ich schätze das es auch in die tl_news mit rein muss, oder?

    Das ganze ist aber unabhängig der Erweiterung contao-news_categories.
    Hintergund ist folgender:

    Bei der Seite handelt es sich um eine Homepage einer Feuerwehr. Wenn ein Eintrag in der Kategorie (contao-news_categories) Einsatz erfolgt, wird dazu eine Einsatzstufe vergeben. Diese soll dann als Statistik für das jeweilige Jahr ausgezählt werden.
    Geändert von darkness (20.07.2020 um 08:02 Uhr)

  2. #2
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Das kannst du am besten mit einem parseArticles Hook machen.

  3. #3
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    Danke Spooky,

    mal zum Verständnis. Mittels des parseArticles Hook kann ich die Datenbankabfragen ausführen. Wie kann ich das Ergebnis dann im FE darstellen?

    Ich habe erst an eine Erweiterung des DCA gedacht. Dort könnte ich ja ein neues Feld festlegen. Das führt dann aber auch zur Änderung an der jeweiligen Tabelle in der Datenbank, oder?
    Ein neues Feld benötige ich ja dort nicht, da die Daten ja schon vorhanden sind.


    Die SQL-Abfrage liefert mir zb "6".

    Code:
    $Katergorie_1 = SELECT COUNT(id) FROM `tl_news` WHERE `tl_news`.`einsatzkat` LIKE "B%" AND year(from_unixtime(date)) = 2020
    Gibt es dann im FW sowas in der Art:
    Code:
     $this->Kategorie_1

  4. #4
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Im parseArticles Hook bekommst du ja das Template übergeben. Das Template kannst du daher dann mit beliebigen Werten befüllen.

  5. #5
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    Soweit klappt die Abfrage jetzt.

    SQL aus der Datenabnk und Anzeigen im FE.

    Wie kann ich denn auf das ausgewählte Jahr im News-Menü zugreifen? In meiner Abfrage habe ich
    Code:
    AND year(from_unixtime(date)) = 2020
    Nur das Jahr soll sich dynamisch aus der Auswahl im News-Menü ergeben. Standartmäßig das aktuelle Jahr und beim klicken auf z.B. 2019 soll die SQL-Abfrage entsprechend angepasst werden.

  6. #6
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Das ist ja ein einfacher query parameter. Du kannst dir den RequestStack Service injecten lassen, mit dem du an den aktuellen Request und damit an die query Parameter kommst.

    Oder du nimmst die Legacy Input Klasse von Contao, wenn's "schneller" gehen soll

  7. #7
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    Hat sich erledigt. Habe die Datei ParseArticlesListener.php neu erstellt und nun ist der Fehler weg.

    Ich fürchte ich habe was kaputt gespielt:

    Code:
    TypeError:
    Argument 1 passed to App\EventListener\ParseArticlesListener::onParseArticles() must be an instance of Contao\FrontendTemplate, string given, called in /var/www/clients/client1/web1/ffw-r/contao/vendor/contao/core-bundle/src/Resources/contao/classes/FrontendTemplate.php on line 52
    
      at src/EventListener/ParseArticlesListener.php:19
      at App\EventListener\ParseArticlesListener->onParseArticles('<!-- TEMPLATE START: vendor/bugbuster/contao-visitors-bundle/src/Resources/contao/templates/mod_visitors_fe_invisible.html5 --><!-- indexer::stop --><!-- Template for "only counting", no display in Frontend. --><span class="visitor_count invisible">{{cache_visitors::1::count}}</span><script>document.addEventListener(\'DOMContentLoaded\', function () {    var iWidth  = window.innerWidth  || (window.document.documentElement.clientWidth  || window.document.body.clientWidth);     var iHeight = window.innerHeight || (window.document.documentElement.clientHeight || window.document.body.clientHeight);    var sWidth  = screen.width;    var sHeight = screen.height;    var visitorurl = \'visitors/screencount?vcid=1&scrw=\'+sWidth+\'&scrh=\'+sHeight+\'&scriw=\'+iWidth+\'&scrih=\'+iHeight+\'\';    try {		fetch( visitorurl, { method: \'GET\' , headers: { \'X-Requested-With\': \'XMLHttpRequest\', } } )	    .catch( error => console.error(\'error:\', error) );    } catch (r) {        return;    }    });</script><!-- indexer::continue --><!-- TEMPLATE END: vendor/bugbuster/contao-visitors-bundle/src/Resources/contao/templates/mod_visitors_fe_invisible.html5 -->', 'mod_visitors_fe_invisible')
         (vendor/contao/core-bundle/src/Resources/contao/classes/FrontendTemplate.php:52)
      at Contao\FrontendTemplate->parse()
         (vendor/contao/core-bundle/src/Resources/contao/modules/Module.php:241)
      at Contao\Module->generate()
         (vendor/bugbuster/contao-visitors-bundle/src/Resources/contao/modules/ModuleVisitors.php:74)
      at BugBuster\Visitors\ModuleVisitors->generate()
         (vendor/contao/core-bundle/src/Resources/contao/library/Contao/Controller.php:419)
      at Contao\Controller::getFrontendModule(object(ModuleModel), 'header')
         (vendor/contao/core-bundle/src/Resources/contao/pages/PageRegular.php:168)
      at Contao\PageRegular->prepare(object(PageModel))
         (vendor/contao/core-bundle/src/Resources/contao/pages/PageRegular.php:48)
      at Contao\PageRegular->getResponse(object(PageModel), true)
         (vendor/contao/core-bundle/src/Resources/contao/controllers/FrontendIndex.php:339)
      at Contao\FrontendIndex->renderPage(object(PageModel))
         (vendor/symfony/http-kernel/HttpKernel.php:158)
      at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
         (vendor/symfony/http-kernel/HttpKernel.php:80)
      at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
         (vendor/symfony/http-kernel/Kernel.php:201)
      at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
         (web/index.php:31)
      at require('/var/www/clients/client1/web1/ffw-r/contao/web/index.php')
         (web/app.php:4)
    Ich hatte mal mit dem parseFrontendTemplate Hook herumgetestet. Aber wieder aufgegeben.
    Geändert von darkness (22.07.2020 um 08:49 Uhr)

  8. #8
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Für diesen Hook brauchst du natürlich eine neue Methode mit entsprechender Signatur. Aber warum willst du diesen Hook verwenden? Der andere ist doch viel besser geeignet.

  9. #9
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    Hat sich erledigt. Siehe oben.

    Mein Gedanke dahinter war folgender:

    Die Statistik mit den Einsätzen soll ja nur einmal erzeugt werden. Beim Aufrufen der des Archivs und bei Verwendung des parseArticles Hooks habe ich die Statistikinformationen aber an jedem Nachrichteneintrag. Daher dachte ich es würde reichen den parseFrontendTemplate Hook zu verwenden.

    Danach habe ich den gelöscht und wollte zum "alten" zurück. Hatte dann aber immer diese Fehlermeldung.

  10. #10
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Du kannst die Statistik in deiner Klasse ja auch nur einmalig erzeugen und dann an die Templates weitergeben.

  11. #11
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    So, vielleicht nicht hübsch, aber funktioniert:
    Ich halte den Code hier mal fest.
    Code:
    <?php
    
      // src/EventListener/ParseArticlesListener.php
      namespace App\EventListener;
    
      use Contao\CoreBundle\ServiceAnnotation\Hook;
      use Contao\FrontendTemplate;
      use Contao\Module;
      use Contao\UserModel;
      use Terminal42\ServiceAnnotationBundle\ServiceAnnotationInterface;
    
      use Contao\CoreBundle\Routing\ScopeMatcher;
      use Symfony\Component\HttpFoundation\RequestStack;
    
    
      class ParseArticlesListener implements ServiceAnnotationInterface
      {   
          private $requestStack;
          private $scopeMatcher;
    
    
          public function __construct(RequestStack $requestStack, ScopeMatcher $scopeMatcher)
          {
            $this->requestStack = $requestStack;
            $this->scopeMatcher = $scopeMatcher;
          }
    
    
           /**
           * @Hook("parseArticles")
           */
      
          public function onParseArticles(FrontendTemplate $template, array $newsEntry, Module $module): void
          {   
      
              $request = $this->requestStack->getCurrentRequest();
              $req_year = $request->query->get("year");
              if ( empty($req_year) ) {
                $req_year = date("Y"); 
    
              }
              $result =  $this->getStatsFromDB($req_year);
              $template->stats = $result;
      
      
    
          }
          
          private function getStatsFromDB($news_year): array
          {
    
    
    
            $sql = "SELECT einsatzkat FROM `tl_news` WHERE (einsatzkat LIKE 'B%' or einsatzkat LIKE 'G%' or einsatzkat LIKE 'H%' or einsatzkat LIKE 'S%' or einsatzkat LIKE 'W%')
                   AND year(from_unixtime(date)) = ?" ;
    
    
    
            $database = \Database::getInstance()
                ->prepare($sql)
                ->execute($news_year);
            $result = $database->fetchAllAssoc();
    
            return $result;
          }
      }
    ?>

  12. #12
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Den Scope Matcher kannst du entfernen, da du den ja gar nicht verwendest . Außerdem solltest du keinen schließenden ?> Tag verwenden. Siehe https://www.php-fig.org/psr/psr-12/#22-files
    Und die generelle Einrückung solltest du auch entfernen.

  13. #13
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    @Spooky

    JEtzt muss ich hier doch noch mal Nachfragen.

    Die Einsatzkategorie wird für jeden "Nachricht" festgelegt. Das führt jetzt aber dazu, das ich bei mehreren Newseinträgen die Datenbankabfragen mehrfach ausgeführt werden.

    Ich habe z.B drei Nachrichten erstellt und die Kategorie vergeben.

    Am Ende sieht das Array so aus:
    Code:
    array(3) { [0]=> array(1) { ["einsatzkat"]=> string(2) "B2" } [1]=> array(1) { ["einsatzkat"]=> string(2) "B3" } [2]=> array(1) { ["einsatzkat"]=> string(2) "B2" } } array(3) { [0]=> array(1) { ["einsatzkat"]=> string(2) "B2" } [1]=> array(1) { ["einsatzkat"]=> string(2) "B3" } [2]=> array(1) { ["einsatzkat"]=> string(2) "B2" } } array(3) { [0]=> array(1) { ["einsatzkat"]=> string(2) "B2" } [1]=> array(1) { ["einsatzkat"]=> string(2) "B3" } [2]=> array(1) { ["einsatzkat"]=> string(2) "B2" } } array(3) { [0]=> array(1) { ["einsatzkat"]=> string(2) "B2" } [1]=> array(1) { ["einsatzkat"]=> string(2) "B3" } [2]=> array(1) { ["einsatzkat"]=> string(2) "B2" } } array(3) { [0]=> array(1) { ["einsatzkat"]=> string(2) "B2" } [1]=> array(1) { ["einsatzkat"]=> string(2) "B3" } [2]=> array(1) { ["einsatzkat"]=> string(2) "B2" } } array(3) { [0]=> array(1) { ["einsatzkat"]=> string(2) "B2" } [1]=> array(1) { ["einsatzkat"]=> string(2) "B3" } [2]=> array(1) { ["einsatzkat"]=> string(2) "B2" } }

    Ich nehme an das es hier dran liegt:

    Code:
    public function onParseArticles(FrontendTemplate $template, array $newsEntry, Module $module): void
        {   
    
            $request = $this->requestStack->getCurrentRequest();
            $req_year = $request->query->get("year");
    
            if ( empty($req_year) ) {
                $req_year = date("Y");
            }
    
            $result =  $this->getStatsFromDB($req_year);
            $template->stats = $result;
        }
    bzw hier:


    Code:
        private function getStatsFromDB($news_year=2020): array
        {   
    
            $sql = "SELECT einsatzkat FROM `tl_news` WHERE (einsatzkat LIKE 'B%' or einsatzkat LIKE 'G%' or einsatzkat LIKE 'H%' or einsatzkat LIKE 'S%' or einsatzkat LIKE 'W%')
                AND year(from_unixtime(date)) = ?" ;
    
            $database = \Database::getInstance()
                ->prepare($sql)
                ->execute($news_year);
            $result = $database->fetchAllAssoc();
    
            return $result;
        }
    Für Jeden Artikel wird eine Datenbankabfrage ausgeführt. Aber es würde ja reichen, die SQL-Abfrage einmalig auszuführen. Gibt es eine Möglichkeit das Problem zu umgehen?
    Ich könnte ja prüfen, ob das Array schon befüllt ist und dann einfach die Abfrage überspringen. Aber wäre das der richtige Weg? Oder gibt es einen Contao-Weg

  14. #14
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Mit Contao hat das nichts zu tun.

    In deiner Klasse könntest du dir ja zB eine statische Member Variable erzeugen, wo du dir das Ergebnis der Datenbankabfrage speicherst. In der Funktion getStatsFromDB überprüfst du dann, ob das Ergebnis schon gesetzt ist, wenn nicht, machst du die Datenbankabfrage und setzt das Ergebnis (und gibst es zurück). Wenn ja, gibst du das bereits gespeicherte Ergebnis zurück.

  15. #15
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    Auch das hat dank deiner Hilfe geklappt. Ich denke ich bin das am Ziel

    Jetzt habe ich im Template news_latest_ffw.html5 folgenden Code eingefügt:

    Code:
    <div class ="statistik">
    	<p><?php echo $this->dev_stats[Brandeinsätze]?> Brandeins&auml;tze</p>
    	<p><?php echo $this->dev_stats[Gefahrstoffeinsätze]?> Gefahrstoffeins&auml;tze</p>
    	<p><?php echo $this->dev_stats[Hilfeleistungseinsätze]?> Hilfeleistungseins&auml;tze</p>
    	<p><?php echo $this->dev_stats[Sicherungsdienste]?> Sicherungsdienste</p>
    	<p><?php echo $this->dev_stats[Wasserrettungseinsatz]?> Wasserrettungseins&auml;tze</p>
    </div>
    Damit bekomme ich wie erwartet die Anzahl angezeigt. Nur leider vor jedem News-Artikel. Daher habe ich den Code nach mod_newsarchive_ffw.html5 verschoben. Da funktioniert es dann leider nicht mehr. Ich nehme an, dass der ParseArticleHook dort noch nicht bzw überhaupt nicht ausgeführt wird, oder?

  16. #16
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Jetzt wird es ein wenig verwirrend . In deinem ersten Post hast du geschrieben, dass du tl_news um ein Feld erweitert hast und du nun anhand des Inhalts dieses Feldes nun zusätzliche Informationen für jede Nachricht anzeigen lassen möchtest. Ist das nun nicht mehr der Fall?

    Wenn es dir nun nur darum geht unabhängig von einer Nachrichtenliste oder einzelnen Nachrichten gewisse Informationen anzuzeigen (die vielleicht aus tl_news Einträgen aggregiert werden), dann solltest du dafür vielleicht ein eigenes Inhaltselement oder Modul programmieren.

  17. #17
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    Zitat Zitat von Spooky Beitrag anzeigen
    Jetzt wird es ein wenig verwirrend
    Jetzt erst

    Soweit richtig. Ich habe tl_news erweitert. Dort wird die Einsatzkategorie angegeben.

    Wenn ich aber die Übersichtsseite der Nachrichten aufrufe soll es etwas so aussehen:


    2020 Einsätze

    2 Brandeinsätze
    0 Gefahrstoffeinsätze
    1 Hilfeleistungseinsätze
    0 Sicherungsdienste
    0 Wasserrettungseinsatz


    Nachricht 1 Überschrift B1
    ---
    Nachricht 2 Überschrift B1
    ---
    Nachricht 3 Überschrift H1


    Das dann dynamisch angepasst auf das jeweilige Jahr.

  18. #18
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Ja, das wäre dann ein eigenes Modul.

  19. #19
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    urgs, tut mir leid das es anfangs nicht so deutlich war.
    Naja, so lerne ich Contao kennen. Dann versuche ich mich mal am Modul....

  20. #20
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    Ok, Grundsätzlich ist das Prinzip ja das gleiche. Aber wie kann ich denn meiner ControllerDatei eine Funktion aufrufen. Vorher hatte ich ja die Funktion onParseArticles.

    Oder brauche ich da die services?

  21. #21
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Wie meinst du das?

    Wie du ein eigenes Modul implementierst ist grundsätzlich hier beschrieben: https://docs.contao.org/dev/framewor...t-end-modules/

  22. #22
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    Bei dem Beispiel wird ja die Funktion getResponse aufgerufen. In meinem Modul muss ja auch eine Funktion aufgerufen werden, welche dann den SQL-Datenabruf aufruft und die Daten entsprechend aufbereitet. Oder habe ich da was falsch verstanden?

  23. #23
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.894
    Partner-ID
    10107

    Standard

    Die Methode getResponse wird nicht von dir aufgerufen. Du implementierst sie nur.

  24. #24
    Contao-Nutzer
    Registriert seit
    18.06.2017.
    Beiträge
    219

    Standard

    Ah, ich glaube jetzt habe ich es verstanden.

    In Modulen wird immer die Funktion getResponse implementiert und dann von Contao entsprechend aufgerufen. Ich dachte ich müsse eine eigene Funktion schreiben um dann das Modul "zu starten". Sorry, kann es leider nicht besser beschreiben.

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Lesezeichen

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •