【问题标题】:Magento getSingleton() vs getModel() issueMagento getSingleton() vs getModel() 问题
【发布时间】:2013-09-12 06:19:51
【问题描述】:

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

谁能解释一下这个区别?

【问题讨论】:

  • Mage::getSingleton 获取已经存在的对象。 Mage::getModel 是一个新的对象。
  • @MagikVishal:单例不仅会返回已经存在的对象。它将首先检查对象是否存在,如果不存在,它将创建一个用于所有进一步调用的对象。

标签: php magento singleton


【解决方案1】:

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

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

【讨论】:

  • -&gt;load(ID) 不会使 singleton 加载新产品 ID。我认为我们只将模型对象存储在注册表中。通过load() 关联的产品 ID 是如何工作的?
  • 加载时会填充新产品的数据。正如 Marius 在下面指出的:如果您有一些当前产品的数据集,而您将加载的产品中不存在,则这些数据不会被覆盖并保持不变......
【解决方案2】:

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,请在调用load 之前使用$model-&gt;setData(array())。这将重置所有属性。

【讨论】:

    【解决方案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】:

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

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

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

      【讨论】:

      • 为什么-&gt;load($product['id'])无法通过单例加载新模型?
      • 加载会覆盖数据。因此,如果例如在第一个产品中有一个“sku”,它将被覆盖。如果某些东西只存在于第一个产品中而不存在于第二个产品中,那么第二个产品可能具有第一个值。
      • 想接受你的回答,但@KennyDs 是第一个回答的。
      【解决方案5】:

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

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

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

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

      【讨论】:

      • 我猜你的意思是“不必加载每个属性”,对吧?
      • 您正确理解了问题,但$products 不是产品集合。但它是一个 Quotecollection。
      • 那么你可以使用: $product = Mage::getModel('catalog/product')->load($id, 'credits');这不会加载所有属性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-03
      • 2013-09-17
      • 1970-01-01
      • 2014-02-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多