web-dev-qa-db-fra.com

Magento getSingleton () vs getModel () problème

Je souhaite parcourir une série d'ID de produit dans Magento. Dans la boucle, j'affiche certains attributs personnalisés des produits comme:

foreach ($products as $product) {
   $model = Mage::getSingleton('catalog/product')->load($product['id']);
   echo '<br>' . $model->getCredits();
}

Le problème est que si la valeur de getCredits() pour le premier élément est true alors tous les éléments suivants affichent true même s'ils n'ont pas la valeur true.

Mais lorsque j'utilise Mage::getModel() au lieu de Mage::getSingleton(), les valeurs d'attribut sont affichées correctement.

Quelqu'un peut-il expliquer cette différence?

14
Arvind Bhardwaj

Mage :: getModel () retournera toujours un nouvel objet pour le modèle donné:

/**
 * Retrieve model object
 *
 * @link    Mage_Core_Model_Config::getModelInstance
 * @param   string $modelClass
 * @param   array|object $arguments
 * @return  Mage_Core_Model_Abstract|false
 */
public static function getModel($modelClass = '', $arguments = array())
{
    return self::getConfig()->getModelInstance($modelClass, $arguments);
}

Mage :: getSingleton () vérifiera si l'objet du modèle donné existe déjà et le retournera si c'est le cas. S'il n'existe pas, il créera un nouvel objet du modèle donné et mettra dans le registre qu'il existe déjà. Le prochain appel ne renverra pas un nouvel objet mais celui existant:

/**
 * Retrieve model object singleton
 *
 * @param   string $modelClass
 * @param   array $arguments
 * @return  Mage_Core_Model_Abstract
 */
public static function getSingleton($modelClass='', array $arguments=array())
{
    $registryKey = '_singleton/'.$modelClass;
    if (!self::registry($registryKey)) {
        self::register($registryKey, self::getModel($modelClass, $arguments));
    }
    return self::registry($registryKey);
}

Dans votre cas, vous voulez toujours un objet/modèle de produit complètement nouveau car chaque produit est unique ...

30
Kenny

getModel renverra à chaque fois une nouvelle instance du modèle demandé.
getSingleton renverra toujours la même instance. C'est l'implémentation du modèle de conception Singleton pour Magento.
Il y a aussi un autre aspect que vous devez garder à l'esprit. La méthode load ne supprime pas toutes les données que vous avez définies sur l'instance de produit. Par exemple, si vous faites cela:

$model = Mage::getModel('catalog/product')->setData('some_field_that_does_not_exist', 1);
$model->load(3);
echo $model->getData('some_field_that_does_not_exist'); //this prints 1

C'est le cas pour toi. En utilisant getSingleton la deuxième fois, vous obtenez la même instance de produit que la première fois. Et lors de l'appel de load, la valeur de credits n'est pas remplacée car il n'y a pas une telle valeur sur le produit nouvellement chargé.
Conclusion: N'utilisez pas getSingleton. Utilisez getModel. Ou si vous voulez utiliser getSingleton utilisez $model->setData(array()) avant d'appeler load. Cela réinitialisera tous les attributs.

10
Marius

vous utilisez Singleton lorsque vous ne voulez qu'une seule instance d'un objet dans toute l'application. Ainsi, lorsque vous utilisez getSingleton, il renvoie toujours le même objet qui peut charger des données plus tôt.

Donc, dans ce cas, lorsque la boucle démarre, il crée un nouvel objet (bien sûr seulement si cela n'a pas été fait auparavant dans un autre endroit de magento) et charge les données pour $ product ['id']. Dans l'itération de la boucle suivante, il prend le même objet avec les données d'ID produit précédentes et y charge de nouvelles données $ product ['id']. C'est pourquoi il peut y avoir des problèmes.

Si vous souhaitez avoir deux produits différents, vous devez utiliser getModel.

4
Jakub Korupczyński

Je voudrais tout d'abord expliquer la difference between Mage::getSingleton() and Mage::getModel() functions.

Lorsque vous appelez la fonction Mage::getSingleton('catalog/product') magento cherchera dans la mémoire s'il y a un objet disponible. Sinon, il créera un nouvel objet pour la classe Mage_catalog_Model_product. Dans la première itération de la boucle foreach, cela se produit. Mais à partir de la deuxième itération, lorsque magento recherche en mémoire l'objet de classe Mage_catalog_Model_product, il trouve l'objet qui a été appelé lors de la première itération. Magento ne créera donc aucun nouvel objet et appellera à la place le même objet qui est déjà en mémoire.

MAIS,

Si vous utilisez Mage::getModel('catalog/product) cette fonction crée toujours un nouvel objet de la classe Mage_catalog_Model_product Dans la mémoire chaque fois que vous l'appelez. Ainsi, dans la boucle, cette fonction créera un objet par itération.

4
Sukeshini

Vous trouverez la différence entre getModel () et getSingleton () dans les autres réponses.

Mais si vous souhaitez accélérer votre code, en supposant que vous ayez une collection, procédez comme suit:

$products->addAttributeToSelect('credits');

foreach ($products as $product) {
   echo '<br>' . $product->getCredits();
}

Vous n'avez donc pas à charger chaque produit, ce qui prend beaucoup de temps.

2
Ralf Siepker