Ergebnis 1 bis 17 von 17

Thema: Hook processFieldSQL und seine Funktion

  1. #1
    Contao-Nutzer
    Registriert seit
    28.01.2011.
    Beiträge
    113

    Standard Hook processFieldSQL und seine Funktion

    Hallo,

    ich habe den Catalog mal nach Hooks durchforstet und in Zeile 2032 den processFieldSQL Hook gefunden. Laut Kommentar können mit seiner Hilfe die SQl-Daten beeinflusst werden. Leider werde ich nicht so wirklich schlau aus dem Code:

    PHP-Code:
        protected function processFieldSQL($arrVisible)
        {
            
    $arrConverted = array();

            
    // iterate all catalog fields
            
    $objFields $this->Database->prepare("SELECT * FROM tl_catalog_fields f WHERE f.pid=(SELECT c.id FROM tl_catalog_types c WHERE c.tableName=?)")
                                       ->
    execute($this->strTable);

            
    $arrFields = array();
            if (
    $objFields->numRows)
            {
                while (
    $objFields->next())
                {
                    
    $row $objFields->row();            
                    
    $arrFields[$row['colName']] = $row;
                }

                foreach (
    $arrVisible as $id=>$field)
                {
                    if (
    array_key_exists($field$arrFields))
                    {
                        switch (
    $arrFields[$field]['type'])
                        {
                            case 
    'calc':
                                
    // set query value to forumla
                                
    $value '('.$arrFields[$field]['calcValue'].') AS '.$field//.'_calc';
                                
    $arrConverted[$id] = $value;
                                break;

                            default:
                                
    $arrConverted[$id] = $field;
                        }

                    }
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    // HOOK: allow third party extension developers to prepare the SQL data
                    
    if(is_array($GLOBALS['TL_HOOKS']['processFieldSQL']) && count($GLOBALS['TL_HOOKS']['processFieldSQL']))
                    {
                        foreach(
    $GLOBALS['TL_HOOKS']['processFieldSQL'] as $callback)
                        {
                            
    $this->import($callback[0]);
                            
    $this->$callback[0]->$callback[1]($this->catalog$id$field$arrFields$arrConverted$this->strTable);
                        }
                    }    
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                
    }    
            }

            return 
    $arrConverted;
        } 
    Kann ich mit Hilfe des Hooks die SQL-Query beeinflussen und wenn ja, wie? Ich würde gerne eine individuelle Sortierreihenfolge integrieren. Ist das möglich?
    Wäre super wenn mir jemande helfen kann, da ich bereits die Zeile

    PHP-Code:
    $this->$callback[0]->$callback[1]($this->catalog$id$field$arrFields$arrConverted$this->strTable); 
    in ihrer Wirkung nicht verstehe.

    Viele Grüße

  2. #2
    Contao-Urgestein Avatar von the_scrat
    Registriert seit
    24.02.2010.
    Ort
    Augsburg
    Beiträge
    2.051
    User beschenken
    Wunschliste

    Standard

    Hallo Erdpferd,

    die SQL-Query kannst du damit nicht beeinflussen, die ist zum Zeitpunkt des Hooks bereits vollständig duchlaufen.
    Mit dem Hook kannst du eine eigene Methode registrieren, die die Parameter
    $this
    ->catalog, $id, $field, $arrFields, $arrConverted, $this->strTable

    übergibt. Die Sortierreihenfolge kannst du allerdings im Modul auch selbst bestimmen. Dazu gibt es im Modul einen Bereich unter Feld-Filter namens "Anordnen nach" dort kannst du die Spalten reinschreiben nach denen sortiert werden soll.

    Hoffe ich konnte dir damit weiterhelfen.

  3. #3
    Contao-Nutzer
    Registriert seit
    28.01.2011.
    Beiträge
    113

    Standard

    Danke für die schnelle Antwort.

    Leider habe ich das Problem, dass ich nicht nach Spalten sortieren will, sondern nach einer Sortierung, die sich durch Formulareingaben des Nutzers ergeben. Eine normale Sortierung nach ASC oder DESC hilft mit dabei nicht weiter. Deshalb meine Hoffnung in die SQL-Query eingreifen zu können.

    Wenn ich $this->catalog bekomme, habe ich dann den ganzen oder nur die Einträge, die auf der jeweiligen paginierten Seite stehen? Für die Sortierung brauche ich nämlich alle Einträge, die dann so sortiert auf die einzelnen Seiten verteilt werden können.

  4. #4
    Contao-Urgestein Avatar von the_scrat
    Registriert seit
    24.02.2010.
    Ort
    Augsburg
    Beiträge
    2.051
    User beschenken
    Wunschliste

    Standard

    Ich kann mir leider nur sehr schlecht vorstellen, was du machen möchtest. Aber selbst wenn du in die SQL eingreifen "könntest", würde dir das ja nix nützen, da der Catalog ja erstmal mit dem Ergebnis das da zurückommt weiterarbeitet.

    Evtl. ist eine Lösung, wenn du das direkt im Template löst. Dort hast du alle Informationen und Felder. Lass diese doch erst in ein Array laufen und dann ausgeben, wie du das meinst. Das kannst du ja dort auch über einen GET oder POST Parameter laufen machen. Vielleicht ist das die einfachste und schnellste und ggf. beste Methode.

  5. #5
    Contao-Nutzer
    Registriert seit
    28.01.2011.
    Beiträge
    113

    Standard

    Bekomme ich im Template nicht auch wieder nur eine Seite, wenn die Paginierung aktiv ist. Die meisten Probleme ergeben sich leider, weil eine Paginierung gesetzt ist und zudem ein Endless-Scroll die einzelnen Seiten nachladen soll. Das Script habe ich hier gefunden:

    https://www.contao-community.de/show...scroll+catalog

    Ich muss also irgendwie an alle Catalogeinträge kommen, um diese individuell zu sortieren. Die einzelnen Seiten zu sortieren hilft leider nicht.

    Ziel der ganzen Sache ist eine Umkreissuche. Die einzelnen Einträge werden mit einer Entfernung zu einer eingegebenen Adresse versehen und sollen dann nach Entfernung sortiert werden. Dafür muss aber die gesamte Liste sortiert werden, genau wie sie gefiltert werden soll, wenn die Entfernung zu groß ist. Durch die Paginierung habe ich aber leider nie alle Einträge gleichzeitig im Template. Deshalb mein Ansatz die SQL-Query zu verändern, so dass ich eine eigene Sortierung und Filterung unterbringen kann.

  6. #6
    Contao-Urgestein
    Registriert seit
    07.04.2010.
    Ort
    Stuttgart
    Beiträge
    2.733
    User beschenken
    Wunschliste

    Standard

    Falls du wirklich "nur" die Sortierung anhand einer Nutzereingabe ändern willst kannst du das im Modul unter "Sortierreihenfolge" machen.
    Dort kannst du Post oder Get Daten via Inputvar einsetzen.

    Edit: Okay eine Umkreissuche also :-)

    Das hatte ich einmal auf meinen Fall zugeschnitten mit eigenem FE-Modul realisiert. Mhh... bin gespannt auf deine Lösung :-)
    Geändert von psren (02.05.2012 um 19:22 Uhr)

  7. #7
    Contao-Urgestein
    Registriert seit
    07.04.2010.
    Ort
    Stuttgart
    Beiträge
    2.733
    User beschenken
    Wunschliste

    Standard

    Zitat Zitat von the_scrat Beitrag anzeigen
    die SQL-Query kannst du damit nicht beeinflussen, die ist zum Zeitpunkt des Hooks bereits vollständig duchlaufen.
    Ohne es getestet zu haben sehe ich das anders. Es ist nur das Query abgefeuert worden, dass die Felder aus der Feld-Tabelle holt. Der eigentlich relevante Query kommt erst später.

    PHP-Code:
    protected function fetchCatalogItems(array $arrFields$strWhere ='',
                                                                                    array 
    $arrParams =array(),
                                                                                    
    $strOrder =''$intLimit =0,
                                                                                    
    $intOffset =0, array $arrJoins=array())
        {
            
    $table $this->objCatalogType->tableName;
          
    $arrFields $this->processFieldSQL($arrFields$this->catalog$table);
          
          
    // prepend columns to minimize the possibility of collisions when using JOINs
          
    foreach ($this->systemColumns as $sysField)
          {
            
    $arrFields[] = sprintf('%s.%s AS %s',
                
    $table$sysField$sysField);
          }
        
          if(
    $this->objCatalogType->aliasField)
            
    $arrFields[] = $this->objCatalogType->aliasField;
          
          
    $strJoins '';
          if(
    $arrJoins)
            
    $strJoins str_replace('{{table}}'$tableimplode(' '$arrJoins));
          
          
    $strOrder strlen($strOrder) ? " ORDER BY " $strOrder "";
          
    $strWhereOrder = ($strWhere?" AND " $strWhere:'') . $strOrder;
          
          
    // pid
          
    $params = array($this->objCatalogType->id);
          
    $params array_merge($params$arrParams);
                
          
    // Run Query
          
    $objCatalogStmt $this->Database->prepare(sprintf('SELECT %1$s,
              "%2$s" AS catalog_name, %3$u AS parentJumpTo
              FROM %4$s %5$s WHERE pid=? %6$s'
    ,
              
    implode(','$arrFields),
                  
    $this->objCatalogType->name,
                  
    $this->objCatalogType->jumpTo,
              
    $table,
              
    $strJoins,
              
    $strWhereOrder));
          
          
    // Limit result
          
    if ($intLimit 0)
            
    $objCatalogStmt->limit($intLimit$intOffset);
          
          return 
    $objCatalogStmt->execute($params);
        } 
    Ja, da wird erst der eigentliche Query ausgeführt, logischerweise nach dem Hook. Also suchst du schonmal an der richtigen Stelle.

    Allerdings habe ich hier grade keine Installation zum rumprobieren :-)

  8. #8
    Contao-Nutzer
    Registriert seit
    28.01.2011.
    Beiträge
    113

    Standard

    Danke für die Antworten.

    Das ist doch mal eine Richtung in der ich weiterarbeiten kann. Vielen Dank. Ich werde berichten.

  9. #9
    Contao-Urgestein
    Registriert seit
    07.04.2010.
    Ort
    Stuttgart
    Beiträge
    2.733
    User beschenken
    Wunschliste

    Standard

    Wenn du nochmals Hilfe brauchst melde dich einfach :-)

    Schön wäre es wenn am Ende ein wiederverwendbares Modul herauskommen würde :-) Du hast mich erst auf den Hook gebracht, den hatte ich beim letzten mal übersehen... leider...

  10. #10
    Contao-Urgestein
    Registriert seit
    07.04.2010.
    Ort
    Stuttgart
    Beiträge
    2.733
    User beschenken
    Wunschliste

    Standard

    Zitat Zitat von the_scrat Beitrag anzeigen
    Evtl. ist eine Lösung, wenn du das direkt im Template löst. Dort hast du alle Informationen und Felder. Lass diese doch erst in ein Array laufen und dann ausgeben, wie du das meinst.
    Das ist leider keine Lösung, da viel zu viele Daten aus der Datenbank kommen. Bei vielen Einträgen ist das ein riesen Array den man sortieren müsste. Die Datenbank löst das irgendwie performanter.

    Hier gibt es ein paar Interessante Infos. Wobei ich mit Haversine als Stored Procedure ~17.000 Locations relativ performant sortiere ;-)

  11. #11
    Contao-Urgestein Avatar von the_scrat
    Registriert seit
    24.02.2010.
    Ort
    Augsburg
    Beiträge
    2.051
    User beschenken
    Wunschliste

    Standard

    Öhm, ja, schon klar, aber als ich das geschrieben habe, lagen nur wenige Informationen vor. Hätte ja auch sein können, dass 20 oder 50 Datensätze verarbeitet werden sollen, dann wäre die Templatelösung absolut akzeptabel.
    Dass es sich um eine Umkreissuche handelt, wurde erst 1 Stunde danach klar, somit fällt logischerweise so eine Lösung weg ;-)

  12. #12
    Contao-Urgestein
    Registriert seit
    07.04.2010.
    Ort
    Stuttgart
    Beiträge
    2.733
    User beschenken
    Wunschliste

    Standard

    Zitat Zitat von the_scrat Beitrag anzeigen
    Öhm, ja, schon klar, aber als ich das geschrieben habe, lagen nur wenige Informationen vor. Hätte ja auch sein können, dass 20 oder 50 Datensätze verarbeitet werden sollen, dann wäre die Templatelösung absolut akzeptabel.
    Dass es sich um eine Umkreissuche handelt, wurde erst 1 Stunde danach klar, somit fällt logischerweise so eine Lösung weg ;-)
    Klar :-) Ich wollte es nur nocheinmal für spätere Leser verdeutlichen wieso jetzt "so umsändlich" :-D

  13. #13
    Contao-Nutzer
    Registriert seit
    28.01.2011.
    Beiträge
    113

    Standard

    Es ist schon eine ganze Weile vergangen aber ich wollte mal meinen letzten Stand präsentieren. Mit dem processFieldSQL-Hook lassen sich die SQL-Abrufe durch den Catalog nicht beeinflussen. So musste ich für die Umkreissuche dem Catalog u.a. einen eigenen Hook implementieren, der die Variable $strWhere übergibt, bevor sie dem Datenbankabruf zugeführt wird. Auf die gleiche Weise war für die Sortierung (in meinem Fall nach Entfernungen) ein neuer Hook nötig (für die Variable $strOrder).

    Da das ganze nicht Updatesicher ist, wird da momentan wohl eher kein eigenes Modul draus. Die zusätzliche Filterung für die Entfernungen habe ich über ein kleines Formular gelöst, dessen Werte im Hook ausgelesen und verarbeitet werden, da der Catalog auch hier keine Lösung ermöglichte. Zumindest keine, die mir eingefallen wäre.

    Viele Grüße

  14. #14
    Contao-Urgestein Avatar von Tim G
    Registriert seit
    13.02.2010.
    Ort
    Lübeck
    Beiträge
    2.210
    User beschenken
    Wunschliste

    Standard

    Hi Leute,
    ja, der processFieldSQL Hook erwartet leider keinen Rückgabewert.

    Die Idee von psren mit inputvar eine POST bzw. GET Variable zu setzen, ist in meinen Augen die eleganteste.
    Du kannst all deine Berechnungen etc. für die nötige Distanz z.B. im parseFrontendTemplate Hook machen, danach die POST Variable FORM_SUBMIT (oder wie dein Form auch identifiziert wird) löschen, damit die Berechnung nur einmal ausgeführt wird und am Ende einfach die neue POST Variable setzen auf die dann inputvar greift, die im Katalog-Liste Modul per Inserttag schlummert.

    Damit kannst du natürlich jedes Feld in den Modul-Einstellungen befeuern. Z.B. auch das Bedingungsfeld.

    Sollte klappen.

    Grüße,
    Tim
    ps. oder generatePage HOOK, alles was früher gefeuert wird als das Modul selbst.
    http://www.tim-gatzky.de ˙ auch schon wieder 2 Jahre alt - wie die Zeit vergeht... muss mal umbauen.

  15. #15
    Contao-Nutzer
    Registriert seit
    28.01.2011.
    Beiträge
    113

    Standard

    Aber wenn ich es richtig verstanden habe, dann kann ich bei einem mehrseitigen Katalog immer nur eine Seite sortieren. Der Hook wird ja folgendermaßen beschrieben:

    Der parseFrontendTemplate-Hook wird bei der Aufbereitung eines Frontend-Templates ausgeführt. Er übergibt Inhalt und Name des Templates als Argument und erwartet den geänderten Template-Inhalt als Rückgabewert.

    Im Modul selbst wird das Template ja aber bereits auf die benötigten Einträge der Seite reduziert, so dass ich immer nur eine Seite sortiere. Der Katalog soll aber mehrseitig sein und via Ajax die Seiten im Endlesspage-Style nachgeladen werden. Dafür habe ich das Script aus diesem Post verwendet:

    https://www.contao-community.de/show...ndless+catalog

    Folgendes Vorgehen habe ich aber auch nicht ganz verstanden:

    ...danach die POST Variable FORM_SUBMIT (oder wie dein Form auch identifiziert wird) löschen, damit die Berechnung nur einmal ausgeführt wird und am Ende einfach die neue POST Variable setzen auf die dann inputvar greift, die im Katalog-Liste Modul per Inserttag schlummert.

    Damit kannst du natürlich jedes Feld in den Modul-Einstellungen befeuern. Z.B. auch das Bedingungsfeld.
    Was genau sollte ich denn in die POST Variable schreiben? Alle Entfernungen für die Einträge? Ich glaube ich steh grad auf der Leitung. Sorry.

  16. #16
    Contao-Urgestein Avatar von Tim G
    Registriert seit
    13.02.2010.
    Ort
    Lübeck
    Beiträge
    2.210
    User beschenken
    Wunschliste

    Standard

    In die Variable schreibst du die Art der Sortierung rein.

    Du kannst auch den getCatalog Hook nutzen. Ich glaube da kommt der gesamte Catalog als Array rein und erwartet ein Array als Rückgabe. Da kannst du auch neusortieren.
    Mit einer Pagination wird es schon schwieriger. Ich bin mir nicht sicher ob der getCatalog Hook vor oder nach dem Aufbau der Pagination aufgerufen wird. Aber bei der Ajax-Variante ohne Pagination spielt das keine Rolle.

    Viel Erfolg
    http://www.tim-gatzky.de ˙ auch schon wieder 2 Jahre alt - wie die Zeit vergeht... muss mal umbauen.

  17. #17
    Contao-Urgestein
    Registriert seit
    07.04.2010.
    Ort
    Stuttgart
    Beiträge
    2.733
    User beschenken
    Wunschliste

    Standard

    Wenn ich mich recht errinnere gibt es mit der Pagination keine Probleme.

    Wenn ich euch helfen konnte könnt ihr euch gerne mal
    meine Amazon Wunschliste anschauen. Dankeschön.

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
  •