Una de las primeras cuestiones que se encuentra un programador en Magento es que es necesario ser estricto en el uso de los recursos (memoria y CPU), ya que en caso contrario es fácil quedarse sin memoria.
Una de las situaciones típicas en este proceso son el manejo de colecciones de productos. La carga de una página de categoría que contenga una docena de productos no es un problema, pero sí lo es cuando queremos procesar centenares o miles de productos en bloque. En ese caso, no es extraño acabar viendo un mensaje como éste:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 49 bytes) in ... on line ...
Finalmente, se realiza la llamada al método load(), que es el método que ejecuta realmente la consulta contra el servidor. En ese momento tenemos todos los modelos (que son instancias de la clase modelo correspondiente) en memoria, con todo lo que ello implica:
Mage::getModel("catalog/product")
->getCollection()
->addAttributeToSelect('sku')
->setPage(1)
->setPageSize(10)
->load();
public function walk($query, array $callbacks, array $args=array(), $adapter = null)
{
$stmt = $this->_getStatement($query, $adapter);
$args['idx'] = 0;
while ($row = $stmt->fetch()) {
$args['row'] = $row;
foreach ($callbacks as $callback) {
$result = call_user_func($callback, $args);
if (!empty($result)) {
$args = array_merge($args, $result);
}
}
$args['idx']++;
}
return $this;
}
Ojo también al detalle en el interior if (!empty($result)) {...}, porque es interesante. Si enviamos más de una función de callback, la segunda función puede recibir el valor retornado por la primera, y la tercera lo retornado por la segunda, y así hasta el final. Esto nos permite trabajar en operaciones muy atomizadas (como siempre, sin abusar).
También es interesante comprobar que el contenido recuperado de la base de datos se añade al array $args dentro del índice 'row', por lo que los datos retornados del registro estarán en $args['row']. También es interesante darse cuenta que los datos recuperados por fetch ya no son un objeto, sino un Array, por lo que todo lo que rodea al objeto modelo queda al margen de esta operativa.
Bueno pues, dicho esto, ¿cómo llamamos al iterador? Con una pequeña diferencia respecto a antes: dejamos de lado load() y utilizaremos getSelect(). Tomando como base la consulta anterior, puedes quitar los límites
$productos = Mage::getModel("catalog/product")
->getCollection()
->addAttributeToSelect('sku');
Mage::getSingleton('core/resource_iterator')->walk($productos->getSelect(), array('funcionCallback'), array('arg1' => 'nombredemitienda', 'arg2' => 'idioma de la tienda', ...));
function funcionCallback($args) {
print_r($args);
}
Pero por lo comentado arriba, podemos enviar más callbacks, y también podemos enviar callbacks a métodos de este objeto u otros. Para cada caso, las llamadas serían:
© 2007 and beyond Mario Alberich, licensed under CC-BY-SA unless stated otherwise.