14

我想在 Magento 中循环一系列产品 ID。在循环中,我将产品的一些自定义属性显示为:

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

问题是,如果getCredits()第一个项目的值是,true那么所有后续项目都会显示true,即使它们没有值true

但是当我使用Mage::getModel()而不是Mage::getSingleton(),属性值显示正确。

谁能解释一下这个区别?

4

5 回答 5

31

Mage::getModel() 将始终为给定模型返回一个新对象:

/**
 * 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() 将检查给定模型的对象是否已经存在,如果存在则返回。如果它不存在,它将创建给定模型的新对象并将其放入已存在的注册表中。下一次调用不会返回新对象,而是返回现有对象:

/**
 * 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);
}

在您的情况下,您总是想要一个全新的产品对象/模型,因为每个产品都是独一无二的......

于 2013-09-12T06:39:56.640 回答
11

getModel每次都会返回请求模型的新实例。
getSingleton将始终返回相同的实例。它是 Magento 的 Singleton 设计模式的实现。
您还必须记住另一个方面。该load方法不会删除您在产品实例上设置的所有数据。例如,如果您这样做:

$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

这就是你的情况。通过使用getSingleton第二次,您将获得与第一次相同的产品实例。并且调用时load的值credits不会被覆盖,因为新加载的产品上没有这样的值。
结论:不要使用getSingleton。使用getModel. 或者,如果您想在调用之前使用getSingletonuse 。这将重置所有属性。$model->setData(array())load

于 2013-09-12T06:43:31.300 回答
5

首先我想解释一下difference between Mage::getSingleton() and Mage::getModel() functions.

当您调用该函数时,Mage::getSingleton('catalog/product')magento 将在内存中搜索是否有可用的对象。如果不是,它将为Mage_catalog_Model_product类创建一个新对象。在 foreach 循环的第一次迭代中会发生这种情况。但是从第二次迭代开始,当 magento 在内存中搜索 Mage_catalog_Model_product 类对象时,它会找到在第一次迭代中调用的对象。所以magento不会创建任何新对象,而是会调用内存中已经存在的同一个对象。

但,

如果你使用Mage::getModel('catalog/product)这个函数,Mage_catalog_Model_product每当你调用它时,总是会在内存中创建新的类对象。所以在循环中,这个函数每次迭代都会创建一个对象。

于 2013-09-12T08:56:34.033 回答
4

当您在整个应用程序中只想要一个对象的一个​​实例时,您可以使用 Singleton。因此,当您使用 getSingleton 时,它总是返回相同的对象,该对象可以更早地加载一些数据。

因此,在这种情况下,当循环开始时,它会创建新对象(当然,前提是之前在 magento 的其他地方没有这样做)并为 $product['id'] 加载数据。在下一次循环迭代中,它采用与先前产品 id 数据相同的对象并将新的 $product['id'] 数据加载到该对象中。这就是为什么会出现一些问题的原因。

如果您想拥有两种不同的产品,则必须使用 getModel。

于 2013-09-12T06:41:47.567 回答
2

您会在其他答案中找到 getModel() 和 getSingleton() 之间的区别。

但是,如果您想加快代码速度,假设您有一个集合,请执行以下操作:

$products->addAttributeToSelect('credits');

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

因此,您不必加载每个产品,这非常耗时。

于 2013-09-12T08:41:34.253 回答