Я хочу перебрать массив идентификаторов продуктов в Magento. В цикле я показываю некоторые пользовательские атрибуты продуктов как:
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 :: 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); }
В вашем случае вы всегда хотите совершенно новый объект / модель продукта, поскольку каждый продукт уникален …
getModel
будет возвращать новый экземпляр запрашиваемой модели каждый раз.
getSingleton
всегда будет возвращать один и тот же экземпляр. Это реализация шаблона проектирования Singleton для Magento.
Существует и другой аспект, который вы должны иметь в виду. Метод 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
. Это приведет к сбросу всех атрибутов.
вы используете Singleton, если хотите только один экземпляр объекта в целом приложении. Поэтому, когда вы используете getSingleton, он всегда возвращает тот же объект, который может иметь некоторые ранее загруженные данные.
Поэтому в этом случае при запуске цикла создается новый объект (конечно, только если это не было сделано раньше в каком-либо другом месте в magento) и загружает данные для $ product ['id']. В следующей итерации цикла он принимает тот же объект с предыдущими данными идентификатора продукта и загружает в него новые данные $ product ['id']. Вот почему могут возникнуть некоторые проблемы.
Если вы хотите иметь два разных продукта, вы должны использовать getModel.
Прежде всего, я хотел бы объяснить 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
в памяти всякий раз, когда вы его вызывали. Таким образом, в цикле эта функция создаст один объект на итерацию.
Вы найдете разницу между getModel () и getSingleton () в других ответах.
Но если вы хотите ускорить свой код, если у вас есть коллекция, сделайте следующее:
$products->addAttributeToSelect('credits'); foreach ($products as $product) { echo '<br>' . $product->getCredits(); }
Поэтому вам не нужно загружать каждый продукт, что очень трудоемко.