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?
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 ...
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.
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.
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.
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.