我正在编写一个模块,它将从一个Magento实例中提取对象,例如网站,组,类别和产品,序列化它们的属性,并将所有内容写入文本文件,进行反序列化以及在另一台服务器上。然后使用这些属性以编程方式在新服务器上重新创建这些对象。我们的想法是,我们将能够提取构成Magento Web商店的所有对象,并将它们移动到另一台服务器。 (不,我们不想将整个实例移动到另一台服务器。我们只是希望能够移动商店及其相关对象。)
显然,由于我们在新服务器上创建类别,因此它们的entity_id将会发生变化。我已经完成了这一部分,并确保子类别具有正确的父ID。在我尝试重新创建类别和子类别对象之前,这个项目大部分都是直截了当的。我遇到各种各样的问题。新类别对象保存数据库。但是,有时它们不会显示在类别树中,有时它们的parent_id会更改为0,有时整个类别树会消失。我一直在研究这个问题大约一个星期。我已经读过你必须在保存之前将'path'属性设置为父路径。我已经读过你必须使用'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();
是的,有些代码有点粗糙。它是一个简化的,我一直在尝试很多东西让它工作。这非常令人沮丧。帮助我Obi-Wan Knobi。你唯一的希望。
答案 0 :(得分:1)
Don!,我花了很多时间研究并努力解决这个问题。互联网上有很多关于这个问题的引用,但到目前为止还没有人提出可靠的解决方案。
Magento使用对象模型来处理所有数据库I / O.这可以使您无需进行繁琐的工作,例如更新相关字段。例如,如果添加新的子类别,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时,我将停止使用数据库。对于那些会说第三人回答你自己的问题的人来说,我说“哈!”