it-swarm.dev

Il modello getListQuery () recupera tutte le righe usando JPagination

Ho metodo getListQuery () nel mio modello, che restituisce query. Come sappiamo, Joomla imposta automaticamente il limite e l'offset sulla query quando utilizziamo JPagination. Ho un problema, voglio usare JPagination e recuperare tutte le righe in getListQuery (). Per quanto riguarda, ho scritto codice come

protected function getListQuery(){

    // here is created my $query object with query

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

    return $query;

}

Significa che la query viene eseguita 2 volte: una da me in questo metodo e una dal core di Joomla. Non sono così contento di questa soluzione, perché provoca un caricamento della pagina 2x più lungo. La query ha circa 10 join ... Con milioni di righe è davvero un problema. Vedi qualche soluzione giusta?

7
turson

Ho trovato una soluzione (penso). Ho sovrascritto i metodi JModelList.

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();

la pagina si carica molto più velocemente. È una buona soluzione?

6
turson

Joomla dovrebbe usare getItems per eseguire la query. Quindi la soluzione migliore è quella di modificare lo stato del modello per assicurarsi che carichi tutti i risultati.

All'interno del modello puoi farlo usando setState in questo modo:

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

Eseguilo prima che il modello chiami getItems e caricherà tutti gli elementi per te.


Alcuni avvertimenti con questo.

  1. Puoi anche farlo al di fuori del modello, quindi se per esempio eri nella tua vista. Puoi fare quanto segue:

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

  2. A volte è possibile farlo troppo presto, prima che lo stato del modello sia stato popolato, il che farà sì che il modello venga ricostruito dallo stato dell'utente dopo aver impostato il limite, praticamente ignorando il limite.

Per risolvere questo problema, è possibile forzare prima il modello a popolare il suo stato:

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

L'attuale metodo populateState è protetto, quindi al di fuori del modello non è possibile chiamarlo direttamente, ma qualsiasi chiamata a getState farà in modo che venga chiamato populateState prima di restituire il impostazioni correnti nello stato.

4
David Fritsch