Magento: правильный способ создания объектов категории
Я пишу модуль, который будет извлекать объекты, такие как веб-сайты, группы, категории и продукты, из одного экземпляра Magento, сериализовывать их свойства и записывать все в текстовый файл, который будет десериализован и на другом сервере. Эти свойства затем используются для программного воссоздания этих объектов на новом сервере. Идея состоит в том, что мы сможем извлечь все объекты, составляющие интернет-магазин Magento, и перенести их на другой сервер. (Нет, мы не хотим перемещать весь экземпляр на другой сервер. Мы просто хотим иметь возможность перемещать магазин и связанные с ним объекты.)
Очевидно, что поскольку мы создаем категории на новом сервере, их entity_id изменится. Я разработал эту часть, а также убедился, что подкатегории имеют правильный родительский идентификатор. Этот проект был в основном простым, пока я не попытался воссоздать объект категории и подкатегории. У меня всевозможные проблемы. Новые объекты категории сохраняют базу данных. Однако иногда они не отображаются в дереве категорий, иногда их parent_id меняется на 0, иногда все дерево категорий исчезает. Я работал над этим около недели. Я прочитал, что вы должны установить свойство 'путь' к пути родительского перед сохранением. Я прочитал, что вы должны использовать метод 'move', чтобы установить категорию, являющуюся дочерней по отношению к ее родителю. Есть много теории, но никто, кажется, не имеет ответа.
Поэтому мой вопрос: как вы создаете записи категорий и подкатегорий, которые на самом деле работают, правильно связаны с родительскими категориями, отображаются в дереве категорий и ничего не изменяют? У меня есть следующие атрибуты из исходной категории источника, хранящиеся в массиве с именем $aryData().
[entity_id] => 127 //This usually changes on new server
[parent_id] => 1 //Lookup NEW entity_id of parent and use it
[path] => //Not sure how to properly set this. Tried a few things
[position] => 8 //Leave this alone, hope for the best
[children_count] => 0 //Have to zero this out when you create new category object
[name] => Best Test
[url_key] => best-test
[is_active] => 1
[include_in_menu] => 1
И вот в общем то, что я делаю, в упрощенном виде:
$objNewCat = Mage::getModel('catalog/category'); //Create new object to populate
$parent_id = getNewParent($data['name'], $data['url-key']; //Get new parent id by name and URL key. (This works)
$objParentCat = Mage::getModel('catalog/category')->load($parent_id);
$aryData(['parent_id']) = $parent_id; //Update parent ID in data array
$aryData(['children_count']) = 0; //Must set to 0. Updated as children are added
$objNewCat->setData($data); //Set all data parameters from our save array
$objNewCat->setPath($objParentCat->getPath()); //Is this correct? Read you have to do this
$objNewCat->save(); //Save object to populate entity_id field
//--- Now assign object to be child of the parent.
$objCat = Mage::getModel('catalog/category')->load($newCat->getId()); //reloading to set 'current category'
Mage::unregister('category');
Mage::unregister('current_category');
Mage::register('category', $objCat);
Mage::register('current_category', $objCat);
$objCat->move($parent_id);
$objCat->save();
Да, часть этого кода довольно грубая. Это упрощено, и я много пробовал, чтобы заставить его работать. Это очень расстраивает. Помоги мне Оби-Ван Кноби. Твоя единственная надежда.
1 ответ
Дон! Я провел много часов, исследуя и борясь с этой проблемой. В Интернете много ссылок на проблему, но никто до сих пор не нашел надежного решения.
Magento использует объектную модель для обработки всех операций ввода-вывода базы данных. Это должно оградить вас от необходимости выполнять утомительную работу, такую как обновление связанных полей. Например, если вы добавите новую дочернюю категорию, объектная модель Magento автоматически обновит 'children_count' в родительской записи. Объектная модель Magento в основном позволяет вам заботиться о данных, которые вы хотите записать, одновременно заботясь о ведении домашнего хозяйства. Однако, когда объектная модель не делает то, что должна, вещи действительно отстой. Это ситуация с полем parent_id и полем path. Magento просто не обновляет их так, как должно.
Решение состоит в том, чтобы внести необходимые изменения с помощью объектной модели, сохранить объект, а затем СДЕЛАТЬ правильные значения для "parent_id" и "path" с помощью запроса к базе данных. Я обнаружил, что поля 'parent_id' и 'path', похоже, правильно сохраняются при первом создании записи, но затем они портятся, если объект обновляется. Этот код предполагает, что вы обновляете существующий объект категории.
$catId = 127; //ID of category record you wish to edit
$objCat = Mage::getModel('catalog/category')->load($catId);
if(!is_object($objCat)) {
throw new Exception("ERROR: Could not find category id: " .$catId);
}
//--- Make sure we have proper parent_id and path values
$parentId = $objCatParent->getId();
$path = $objCatParent->getPath() ."/" .$objCat->getId();
$objCatParent = $objCat->getParentCategory(); //We will need this parent category
$data = array('name' => 'My Cool Category',
'parent_id => $parentId,
'path' => $path;
$objCat->addData($data); //Use 'addData' rather than 'setData'
$objCat->save(); //Save to update record and break parent_id, path fields
//--- Now we get a connection to the database, build a query, and update record
$resource = Mage::getSingleton('core/resource');
$objCon = $resource->getConnection('core_write');
$tableName = "catalog_category_entity"; //Well, it's the name of the Category table
$query = "UPDATE {$table} SET parent_id = {$parentId}, path = '{$path}' "
. " WHERE entity_id = " .$catId;
$objCon->query($query); //Force proper values directly into table
Да, да, да, вы должны быть очень осторожны, когда вы обходите объектную модель и вносите изменения непосредственно в записи базы данных. Однако объектная модель Magento, похоже, здесь не работает, поэтому у нас мало выбора. И поскольку мы сохраняем запись с помощью метода объекта save(), прежде чем он выполняет какую-либо "закулисную" работу, которую он должен делать. Мы просто исправляем ошибку.
Я надеюсь, что это помогает вам. Это была неприятная проблема. Хотелось бы, чтобы было лучшее решение, но когда они исправят API, я перестану играть с базой данных. И для тех из вас, кто скажет, что отвечать на свой вопрос в третьем лице - неудобно, я говорю: "ГА!"