Magento getSingleton()vs getModel()问题

时间:2013-09-12 06:19:52

标签: php magento singleton

我想在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()时,属性值显示正确。

有人可以解释一下这个区别吗?

5 个答案:

答案 0 :(得分:30)

Mage :: getModel()将始终返回给定模型的新Object:

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

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

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

答案 1 :(得分:10)

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。或者,如果您想在调用getSingleton之前使用$model->setData(array())使用load。这将重置所有属性。

答案 2 :(得分:4)

如果在整个应用程序中只需要一个对象实例,则使用Singleton。因此,当您使用getSingleton时,它总是返回可以在之前加载一些数据的相同对象。

因此,在这种情况下,当循环开始时,它会创建新对象(当然,只有在以前没有在magento的其他位置进行过此操作)并加载$ product ['id']的数据。在下一个循环迭代中,它使用与先前产品id数据相同的对象,并向其加载新的$ product ['id']数据。这就是为什么会有一些问题。

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

答案 3 :(得分:3)

首先,我想解释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类的新对象。因此在循环中,此函数将在每次迭代时创建一个对象。

答案 4 :(得分:2)

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

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

$products->addAttributeToSelect('credits');

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

所以你不必加载每件产品,这非常耗时。