Magento - Custom (не EAV) модель, загрузка несколькими полями
-
16-10-2019 - |
Вопрос
У меня есть пользовательская модель и модель ресурсов. Я хочу загрузить один экземпляр модели, используя более 1 поле.
Модель имеет следующие поля:
id
tag_name
custom_name
group_name
Я хочу загрузить эту модель на основе tag_name, custom_name и group_name вместо id.
В настоящее время я использую коллекцию и AddFilter для каждого поля. Это работает, но я задавался вопросом, есть ли стандартная стратегия для такого типа вещей в Magento?
РЕДАКТИРОВАТЬ
Core Magento, кажется, не использует коллекции для этого сценария, а вместо этого использует прямые запросы SQL в моделях ресурсов.
Примером этого является:
loadByAccountAndDate()
в Mage_Paypal_Model_Resource_Report_Settlement
Есть ли причина для этого, когда коллекции кажутся более кратким способом, с точки зрения количества кода, который будет написан
Я просто не знаю, почему Magento решает сделать это таким образом
Решение
Я думаю, что это хороший подход. Может быть, вам нужно создать обертку в классе моделей, чтобы вы не написали одно и то же снова и снова.
Что-то типа:
public function loadByMultiple($tag, $customName, $group){
$collection = $this->getCollection()
->addFieldToFilter('tag_name', $tag)
->addFieldToFilter('custom_name', $customName)
->addFieldToFilter('group_name', $group);
return $collection->getFirstItem();
}
И вы можете загрузить этот элемент в любом другом месте:
$model = Mage::getModel('model/class_here')->loadByMultiple($tag, $customName, $group);
if ($model->getId()){
//the instance exists
}
else{
//not found
}
Другие советы
Модуль/модель/somemodel.php
public function loadByAttributes($attributes)
{
$this->setData($this->getResource()->loadByAttributes($attributes));
return $this;
}
Module/model/resource/somemodel.php:
public function loadByAttributes($attributes)
{
$adapter = $this->_getReadAdapter();
$where = array();
foreach ($attributes as $attributeCode=> $value) {
$where[] = sprintf('%s=:%s', $attributeCode, $attributeCode);
}
$select = $adapter->select()
->from($this->getMainTable())
->where(implode(' AND ', $where));
$binds = $attributes;
return $adapter->fetchRow($select, $binds);
}
И, наконец, вы можете загрузить модель следующей:
$attributes = array('tag_name'=> 'any', 'custome_name'=> 'some','group_name'=>'some');
$model = Mage::getModel('module/somemodel')->loadByAttributes($attributes);
Обновлено
Кстати, вы можете легко использовать этот метод (LoadByAttributes), а не сбор, и это более понятно. Magento также отправляет некоторые события, в то время как загрузка сбора или организации и третьей стороны может обновить сбор или объект обновления Observer. Если вы загружаете сущность через ресурс (приведенный в примере моего и вашего). Никакие события/наблюдатели не стреляют, и вы можете получить «чистую» сущность быстрее, а не сборы. Также Magento не использует кэшированную коллекцию таким образом, он загружает ее непосредственно из таблицы DB.
Может быть, это причина использования этого метода с помощью модулей Magento Core.
Вы делаете это правильно с addFilter
. Анкет В Magento вы можете загрузить любым атрибутом, но не несколько атрибутов одновременно. Добавляя фильтры, вы достигаете того же эффекта без дополнительных накладных расходов.
Во -первых, ваша стратегия фильтрации коллекции верна. Поскольку коллекции в Magento Lazy-загрузке у вас есть возможность создавать методы в модели вашей ресурса, чтобы более тесно определить требования вашей пользовательской нагрузки.
Без некоторого вашего кода к примеру рассмотрите следующий псевдометод в модели ресурса:
<?php
class Marty_Wallace_Model_Resource_Method extends Mage_Core_Model_Resource_Db_Abstract{
protected function _construct()
{
$this->_init('yourmodel/table', 'entity_id');
}
public function loadByCriteria(array $filter)
{
//$filter should be array('columnname'=>'value','columname'=>'value')
$collection = Mage::getModel('yourmodel/class')->getCollection();
foreach($filter as $column=>$value){
$collection->addFieldToFilter($column,$value);
}
return $collection;
}
}