web-dev-qa-db-fra.com

Modèle getListQuery () récupère toutes les lignes à l'aide de JPagination

J'ai la méthode getListQuery () dans mon modèle, qui renvoie la requête. Comme nous le savons, Joomla définit automatiquement la limite et le décalage pour interroger lorsque nous utilisons JPagination. J'ai un problème, je veux utiliser JPagination et récupérer toutes les lignes dans getListQuery (). En ce qui concerne, j'ai écrit du code comme

protected function getListQuery(){

    // here is created my $query object with query

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

    return $query;

}

Cela signifie que la requête est exécutée 2 fois: une par moi dans cette méthode et une par Joomla core. Je ne suis pas satisfait de cette solution car elle entraîne des chargements de page 2x plus longs. Query a environ 10 jointures ... Avec des millions de lignes, c'est vraiment un problème. Voyez-vous une bonne solution?

7
turson

J'ai trouvé une solution (je pense). J'ai écrasé les méthodes 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 page se charge beaucoup plus rapidement. Est-ce une bonne solution?

6
turson

Joomla devrait utiliser getItems pour exécuter la requête. Il est donc préférable de modifier l’état du modèle pour s’assurer que tous les résultats sont chargés.

Dans le modèle, vous pouvez le faire en utilisant setState comme ceci:

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

Exécutez-le avant que le modèle appelle getItems et il chargera tous les éléments pour vous.


Quelques mises en garde avec cela.

  1. Vous pouvez également le faire en dehors du modèle, donc si, par exemple, vous étiez dans votre vue. Vous pouvez faire ce qui suit:

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

  2. Parfois, vous pouvez le faire trop tôt, avant que l'état du modèle ne soit rempli, ce qui entraînera la reconstruction du modèle à partir de l'état utilisateur après que vous ayez défini la limite, dépassant ainsi la limite.

Pour résoudre ce problème, vous pouvez forcer le modèle à renseigner son état en premier:

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

La méthode actuelle populateState est protégée. Par conséquent, en dehors du modèle, vous ne pouvez pas l'appeler directement, mais tout appel à getState s'assurera que le populateState est appelé avant de renvoyer le paramètres actuels dans l'état.

4
David Fritsch