Modell getListQuery () ruft alle Zeilen mit JPagination ab

7

Ich habe die Methode getListQuery () in meinem Modell, die eine Abfrage zurückgibt. Wie wir wissen, hat Joomla bei Verwendung von JPagination automatisch Limit und Offset für die Abfrage festgelegt. Ich habe ein Problem, dass ich JPagination verwenden und alle Zeilen in getListQuery () abrufen möchte. Soweit habe ich Code wie geschrieben

protected function getListQuery(){

    // here is created my $query object with query

    // I'm fetching all rows
    $rows = $db->loadObjectList();
    $this->rows = $rows;

    return $query;

}

Dies bedeutet, dass die Abfrage zweimal ausgeführt wird: eine von mir in dieser Methode und eine von Joomla Core. Ich bin mit dieser Lösung nicht so zufrieden, da sie das Laden von Seiten zweimal länger verursacht. Die Abfrage hat ungefähr 10 Verknüpfungen ... Bei Millionen von Zeilen ist das wirklich ein Problem. Sehen Sie eine richtige Lösung?

Turson
quelle

Antworten:

6

Ich habe eine Lösung gefunden (glaube ich). Ich habe JModelList-Methoden überschrieben.

class MyComponentModel extends JModelList{

    protected $_items = array();

    public function getItems() {
        // Get a storage key.
        $store = $this->getStoreId();

        // Try to load the data from internal storage.
        if (isset($this->cache[$store])) {
            return $this->cache[$store];
        }
        $query = $this->getQuery();
        $this->query = $query;
        $db = JFactory::getDbo();
        $db->setQuery($query);
        $rows = $db->loadObjectList();
        $this->cache[$store] = $rows;
        $this->_items = $rows;
        return array_slice($rows, $this->getStart(), $this->getState('list.limit'));
    }

    public function getPagination() {
        // Get a storage key.
        $store = $this->getStoreId('getPagination');

        // Try to load the data from internal storage.
        if (isset($this->cache[$store])) {
            return $this->cache[$store];
        }

        // Create the pagination object.
        jimport('joomla.html.pagination');
        $limit = (int) $this->getState('list.limit') - (int) $this->getState('list.links');
        $page = new JPagination($this->getTotal(), $this->getStart(), $limit);

        // Add the object to the internal cache.
        $this->cache[$store] = $page;

        return $this->cache[$store];
    }

    function getTotal() {
        return count($this->_items);
    }

    public function getQuery() {
        // query
        return $query;
    }

}

view.html.php

$this->model = $this->getModel();
$this->items = $this->model->getItems();
$this->pagination = $this->model->getPagination();

Seite wird viel schneller geladen. Ist es eine gute Lösung?

Turson
quelle
Warum brauchst du alle Zeilen? Was machst du $this->_itemsin diesem Fall?
David Fritsch
Ich habe Google Maps mit ausgewähltem Standort als Markierungen, daher wollte ich alle Zeilen
abrufen
Ich bin mir ziemlich sicher, dass hiermit immer noch alle Ergebnisse geladen werden. Der Cache speichert die Variable zwischen den Seitenladevorgängen nicht. Ich denke, Joomlas Standardmethode würde gut funktionieren. (Was wahrscheinlich bedeutet, dass mir etwas fehlt ...)
David Fritsch
Ja, es werden alle Ergebnisse bei jedem Laden der Seite geladen, aber meiner Meinung nach wird die Site schneller als früher geladen, wenn ich die Abfrage zweimal ausgeführt habe und die Paginierung
einwandfrei
Laden Sie nicht alle Zeilen, wenn Sie nur 20 sagen müssen. Laden Sie Daten mit: $ db = $ this-> getDbo (); $ db-> setQuery ($ query, $ start, $ limit); Zählen Sie mit: $ this -> _ getListCount ($ query);
ed22
4

Joomla sollte verwenden getItems, um die Abfrage auszuführen. Am besten ändern Sie den Status des Modells, um sicherzustellen, dass alle Ergebnisse geladen werden.

Innerhalb des Modells können Sie dies folgendermaßen tun setState:

$this->setState('list.limit', 0);

Führen Sie dies aus, bevor das Modell getItems aufruft, und es lädt alle Elemente für Sie.


Ein paar Vorbehalte dazu.

  1. Sie können dies auch außerhalb des Modells tun, wenn Sie beispielsweise in Ihrer Ansicht waren. Sie können Folgendes tun:

    $ model = $ this-> getModel (); $ model-> setState ('list.limit', 0);

  2. Manchmal können Sie dies zu früh tun, bevor der Status des Modells ausgefüllt wurde. Dies führt dazu, dass das Modell aus dem Benutzerstatus wiederhergestellt wird, nachdem Sie das Limit festgelegt haben, wodurch das Limit im Wesentlichen überschrieben wird.

Um dies zu beheben, können Sie das Modell zwingen, zuerst seinen Status zu füllen:

$model = $this->getModel();
$model->getState();
$model->setState('list.limit', 0);

Die eigentliche populateStateMethode ist geschützt, sodass Sie sie außerhalb des Modells nicht direkt aufrufen können. Bei jedem Aufruf von getStatewird jedoch sichergestellt, dass die Methode populateStateaufgerufen wird, bevor die aktuellen Einstellungen im Status zurückgegeben werden.

David Fritsch
quelle
Danke für die Antwort. Leider habe ich mein Ziel noch nicht erreicht. Meine view.html.php: $this->model = $this->getModel(); $this->model->getState(); $this->model->setState('list.limit', 0); $this->pagination = $this->get('Pagination'); $this->items = $this->get('Items'); $this->state = $this->get('State');Es bewirkt, dass die Abfrage alle Zeilen auf einer Seite
lädt
Hmm ... ich habe es falsch verstanden. Ich dachte du wolltest ALLE Reihen. Sie möchten tatsächlich alle verfügbaren Zeilen, möchten aber dennoch nur einige der Zeilen anzeigen?
David Fritsch
Ich wollte alle Zeilen
abrufen
Aber was machst du mit all den Zeilen? Wofür lagern Sie sie?
David Fritsch
Ich brauche alle Zeilen, um Koordinationen zu erhalten und Markierungen auf Google Map zu setzen. Auf der Karte müssen alle Markierungen sein.
Turson