Saya mencoba untuk menambahkan pohon Kategori ke ekstensi kustom, pohon kategori yang ada di salah satu tab halaman edit produk
Saya mencoba untuk menambahkan pohon Kategori ke ekstensi kustom, pohon kategori yang ada di salah satu tab halaman edit produk
Jawaban:
Persiapkan diri Anda, ini akan lama. Ini dia.
Anda membutuhkan file-file berikut:
app/code/local/[Namespace]/[Module]/Block/Adminhtml/[Entity]/Edit/Tab/Categories.php
- tab yang akan menyajikan kategori.
<?php
class [Namespace]_[Module]_Block_Adminhtml_[Entity]_Edit_Tab_Categories
extends Mage_Adminhtml_Block_Catalog_Category_Tree {
protected $_categoryIds = null;
protected $_selectedNodes = null;
public function __construct() {
parent::__construct();
$this->setTemplate('[namespace]_module/[entity]/edit/tab/categories.phtml');
$this->_withProductCount = false;
}
public function get[Entity](){
return Mage::registry('current_[entity]'); //use other registration key if you have one
}
public function getCategoryIds(){
if (is_null($this->_categoryIds)){
$categories = $this->get[Entity]()->getSelectedCategories();
$ids = array();
foreach ($categories as $category){
$ids[] = $category->getId();
}
$this->_categoryIds = $ids;
}
return $this->_categoryIds;
}
public function getIdsString(){
return implode(',', $this->getCategoryIds());
}
public function getRootNode(){
$root = $this->getRoot();
if ($root && in_array($root->getId(), $this->getCategoryIds())) {
$root->setChecked(true);
}
return $root;
}
public function getRoot($parentNodeCategory = null, $recursionLevel = 3){
if (!is_null($parentNodeCategory) && $parentNodeCategory->getId()) {
return $this->getNode($parentNodeCategory, $recursionLevel);
}
$root = Mage::registry('category_root');
if (is_null($root)) {
$rootId = Mage_Catalog_Model_Category::TREE_ROOT_ID;
$ids = $this->getSelectedCategoryPathIds($rootId);
$tree = Mage::getResourceSingleton('catalog/category_tree')
->loadByIds($ids, false, false);
if ($this->getCategory()) {
$tree->loadEnsuredNodes($this->getCategory(), $tree->getNodeById($rootId));
}
$tree->addCollectionData($this->getCategoryCollection());
$root = $tree->getNodeById($rootId);
Mage::register('category_root', $root);
}
return $root;
}
protected function _getNodeJson($node, $level = 1){
$item = parent::_getNodeJson($node, $level);
if ($this->_isParentSelectedCategory($node)) {
$item['expanded'] = true;
}
if (in_array($node->getId(), $this->getCategoryIds())) {
$item['checked'] = true;
}
return $item;
}
protected function _isParentSelectedCategory($node){
$result = false;
// Contains string with all category IDs of children (not exactly direct) of the node
$allChildren = $node->getAllChildren();
if ($allChildren) {
$selectedCategoryIds = $this->getCategoryIds();
$allChildrenArr = explode(',', $allChildren);
for ($i = 0, $cnt = count($selectedCategoryIds); $i < $cnt; $i++) {
$isSelf = $node->getId() == $selectedCategoryIds[$i];
if (!$isSelf && in_array($selectedCategoryIds[$i], $allChildrenArr)) {
$result = true;
break;
}
}
}
return $result;
}
protected function _getSelectedNodes(){
if ($this->_selectedNodes === null) {
$this->_selectedNodes = array();
$root = $this->getRoot();
foreach ($this->getCategoryIds() as $categoryId) {
if ($root) {
$this->_selectedNodes[] = $root->getTree()->getNodeById($categoryId);
}
}
}
return $this->_selectedNodes;
}
public function getCategoryChildrenJson($categoryId){
$category = Mage::getModel('catalog/category')->load($categoryId);
$node = $this->getRoot($category, 1)->getTree()->getNodeById($categoryId);
if (!$node || !$node->hasChildren()) {
return '[]';
}
$children = array();
foreach ($node->getChildren() as $child) {
$children[] = $this->_getNodeJson($child);
}
return Mage::helper('core')->jsonEncode($children);
}
public function getLoadTreeUrl($expanded = null){
return $this->getUrl('*/*/categoriesJson', array('_current' => true));
}
public function getSelectedCategoryPathIds($rootId = false){
$ids = array();
$categoryIds = $this->getCategoryIds();
if (empty($categoryIds)) {
return array();
}
$collection = Mage::getResourceModel('catalog/category_collection');
if ($rootId) {
$collection->addFieldToFilter('parent_id', $rootId);
}
else {
$collection->addFieldToFilter('entity_id', array('in'=>$categoryIds));
}
foreach ($collection as $item) {
if ($rootId && !in_array($rootId, $item->getPathIds())) {
continue;
}
foreach ($item->getPathIds() as $id) {
if (!in_array($id, $ids)) {
$ids[] = $id;
}
}
}
return $ids;
}
}
app/design/adminhtml/default/default/[namespace]_[module]/[entity]/tab/edit/categories.phtml
- templat yang diperlukan untuk membuat kategori
<div class="entry-edit">
<div class="entry-edit-head">
<h4 class="icon-head head-edit-form fieldset-legend">
<?php echo Mage::helper('[module]')->__('Categories') ?>
</h4>
</div>
<fieldset id="grop_fields">
<input type="hidden" name="category_ids" id="[entity]_categories" value="<?php echo $this->getIdsString() ?>">
<div id="[entity]-categories" class="tree"></div>
</fieldset>
</div>
<?php if($this->getRootNode() && $this->getRootNode()->hasChildren()): ?>
<script type="text/javascript">
Ext.EventManager.onDocumentReady(function() {
var categoryLoader = new Ext.tree.TreeLoader({
dataUrl: '<?php echo $this->getLoadTreeUrl()?>'
});
categoryLoader.createNode = function(config) {
config.uiProvider = Ext.tree.CheckboxNodeUI;
var node;
if (config.children && !config.children.length) {
delete(config.children);
node = new Ext.tree.AsyncTreeNode(config);
}
else {
node = new Ext.tree.TreeNode(config);
}
return node;
};
categoryLoader.on("beforeload", function(treeLoader, node) {
treeLoader.baseParams.category = node.attributes.id;
});
categoryLoader.on("load", function(treeLoader, node, config) {
varienWindowOnload();
});
var tree = new Ext.tree.TreePanel('[entity]-categories', {
animate:true,
loader: categoryLoader,
enableDD:false,
containerScroll: true,
rootUIProvider: Ext.tree.CheckboxNodeUI,
selModel: new Ext.tree.CheckNodeMultiSelectionModel(),
rootVisible: '<?php echo $this->getRootNode()->getIsVisible() ?>'
});
tree.on('check', function(node) {
if(node.attributes.checked) {
categoryAdd(node.id);
} else {
categoryRemove(node.id);
}
varienElementMethods.setHasChanges(node.getUI().checkbox);
}, tree);
var root = new Ext.tree.TreeNode({
text: '<?php echo $this->jsQuoteEscape($this->getRootNode()->getName()) ?>',
draggable:false,
checked:'<?php echo $this->getRootNode()->getChecked() ?>',
id:'<?php echo $this->getRootNode()->getId() ?>',
disabled: <?php echo ($this->getRootNode()->getDisabled() ? 'true' : 'false') ?>,
uiProvider: Ext.tree.CheckboxNodeUI
});
tree.setRootNode(root);
bildCategoryTree(root, <?php echo $this->getTreeJson() ?>);
tree.addListener('click', categoryClick.createDelegate(this));
tree.render();
root.expand();
});
function bildCategoryTree(parent, config){
if (!config) {
return null;
}
if (parent && config && config.length){
for (var i = 0; i < config.length; i++){
config[i].uiProvider = Ext.tree.CheckboxNodeUI;
var node;
var _node = Object.clone(config[i]);
if (_node.children && !_node.children.length) {
delete(_node.children);
node = new Ext.tree.AsyncTreeNode(_node);
}
else {
node = new Ext.tree.TreeNode(config[i]);
}
parent.appendChild(node);
node.loader = node.getOwnerTree().loader;
if(config[i].children){
bildCategoryTree(node, config[i].children);
}
}
}
}
function categoryClick(node, e){
if (node.disabled) {
return;
}
node.getUI().check(!node.getUI().checked());
varienElementMethods.setHasChanges(Event.element(e), e);
};
function categoryAdd(id) {
var ids = $('[entity]_categories').value.split(',');
ids.push(id);
$('[entity]_categories').value = ids.join(',');
}
function categoryRemove(id) {
var ids = $('[entity]_categories').value.split(',');
while (-1 != ids.indexOf(id)) {
ids.splice(ids.indexOf(id), 1);
}
$('[entity]_categories').value = ids.join(',');
}
</script>
<?php endif; ?>
Di file formulir di mana Anda menambahkan tab entitas kustom Anda, tambahkan ini juga:
$this->addTab('categories', array(
'label' => Mage::helper('[module]')->__('Associated categories'),
'url' => $this->getUrl('*/*/categories', array('_current' => true)),
'class' => 'ajax'
));
Di pengontrol admin entitas kustom Anda, 2 tindakan ini yang akan menangani permintaan untuk kategori:
public function categoriesAction(){
$this->_init[Entity]();
$this->loadLayout();
$this->renderLayout();
}
public function categoriesJsonAction(){
$this->_init[Entity]();
$this->getResponse()->setBody(
$this->getLayout()->createBlock('[module]/adminhtml_[entity]_edit_tab_categories')
->getCategoryChildrenJson($this->getRequest()->getParam('category'))
);
}
dan pastikan bahwa pada kontroler yang sama metode ini ada:
protected function _init[Entity](){
$[entity]Id = (int) $this->getRequest()->getParam('id');
$[enity] = Mage::getModel('[module]/[entity]');
if ($[entity]Id) {
$[entity]->load($[entity]Id);
}
Mage::register('current_[entity]', $[entity]);
return $[entity];
}
Di file tata letak admin modul Anda tambahkan pegangan ini untuk tindakan kategori:
<adminhtml_[module]_[entity]_categories>
<block type="core/text_list" name="root" output="toHtml">
<block type="[module]/adminhtml_[entity]_edit_tab_categories" name="[entity].edit.tab.categories"/>
</block>
</adminhtml_[module]_[entity]_categories>
Sekarang mari kita lanjutkan ke penyimpanan data Anda.
Untuk ini, Anda akan memerlukan yang berikut ini di salah satu skrip instal / peningkatan modul Anda. Ini akan membuat tabel di mana nilai tertaut akan disimpan
$table = $this->getConnection()
->newTable($this->getTable('[module]/[entity]_category'))
->addColumn('rel_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
'unsigned' => true,
'identity' => true,
'nullable' => false,
'primary' => true,
), 'Relation ID')
->addColumn('[entity]_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
'unsigned' => true,
'nullable' => false,
'default' => '0',
), '[Entity] ID')
->addColumn('category_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
'unsigned' => true,
'nullable' => false,
'default' => '0',
), 'Category ID')
->addColumn('position', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
'nullable' => false,
'default' => '0',
), 'Position')
->addIndex($this->getIdxName('[module]/[entity]_category', array('category_id')), array('category_id'))
->addForeignKey($this->getFkName('[module]/[entity]_category', '[entity]_id', '[module]/[entity]', 'entity_id'), '[entity]_id', $this->getTable('[module]/[entity]'), 'entity_id', Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
->addForeignKey($this->getFkName('[module]/[entity]_category', 'category_id', 'catalog/category', 'entity_id'), 'category_id', $this->getTable('catalog/category'), 'entity_id', Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
->addIndex(
$this->getIdxName(
'[module]/[entity]_category',
array('[entity]_id', 'category_id'),
Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
),
array('[entity]_id', 'category_id'),
array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
->setComment('[Entity] to Category Linkage Table');
$this->getConnection()->createTable($table);
Nyatakan meja Anda. Tambahkan ini di config.xml
dalam <[module]_resource><entities>
tag
<[entity]_category>
<table>[module]_[entity]_category</table>
</[entity]_category>
Anda memerlukan model untuk menautkan ke kategori:
app/code/local/[Namespace]/[Module]/Model/[Entity]/Category.php
<?php
class [Namespace]_[Module]_Model_[Entity]_Category
extends Mage_Core_Model_Abstract {
protected function _construct(){
$this->_init('[module]/[entity]_category');
}
public function save[Entity]Relation($[entity]){
$data = $[entity]->getCategoriesData();
if (!is_null($data)) {
$this->_getResource()->save[Entity]Relation($[entity], $data);
}
return $this;
}
public function getCategoryCollection($[entity]){
$collection = Mage::getResourceModel('[module]/[entity]_category_collection')
->add[Entity]Filter($[entity]);
return $collection;
}
}
dan model sumber daya app/code/local/[Namespace]/[Module]/Model/Resource/[Entity]/Category.php
:
<?php
class [Namespace]_[Module]_Model_Resource_[Entity]_Category
extends Mage_Core_Model_Resource_Db_Abstract {
protected function _construct(){
$this->_init('[module]/[entity]_category', 'rel_id');
}
public function save[Entity]Relation($[entity], $data){
if (!is_array($data)) {
$data = array();
}
$deleteCondition = $this->_getWriteAdapter()->quoteInto('[entity]_id=?', $[entity]->getId());
$this->_getWriteAdapter()->delete($this->getMainTable(), $deleteCondition);
foreach ($data as $categoryId) {
if (!empty($categoryId)){
$this->_getWriteAdapter()->insert($this->getMainTable(), array(
'[entity]_id' => $[entity]->getId(),
'category_id' => $categoryId,
'position' => 1
));
}
}
return $this;
}
}
dan model sumber daya koleksi: app/code/local/[Namespace]/[Module]/Model/Resource/[Entity]/Category/Collection.php
<?php
class [Namespace]_[Module]_Model_Resource_[Entity]_Category_Collection
extends Mage_Catalog_Model_Resource_Category_Collection{
protected $_joinedFields = false;
public function joinFields(){
if (!$this->_joinedFields){
$this->getSelect()->join(
array('related' => $this->getTable('[module]/[entity]_category')),
'related.category_id = main_table.entity_id',
array('position')
);
$this->_joinedFields = true;
}
return $this;
}
public function add[Entity]Filter($[entity]){
if ($[entity] instanceof [Namespace]_[Module]_Model_[Entity]){
$[entity] = $[entity]->getId();
}
if (!$this->_joinedFields){
$this->joinFields();
}
$this->getSelect()->where('related.[entity]_id = ?', $[entity]);
return $this;
}
}
Sekarang di saveAction controller admin Anda, tambahkan ini tepat sebelum memanggil $[entity]->save()
$categories = $this->getRequest()->getPost('category_ids', -1);
if ($categories != -1) {
$categories = explode(',', $categories);
$categories = array_unique($categories);
$[entity]->setCategoriesData($categories);
}
Dalam model entitas Anda, tambahkan ini di bagian atas kelas Anda: protected $_categoryInstance = null;
dan metode ini di mana saja:
protected function _afterSave() {
$this->getCategoryInstance()->save[Entity]Relation($this);
return parent::_afterSave();
}
public function getCategoryInstance(){
if (!$this->_categoryInstance) {
$this->_categoryInstance = Mage::getSingleton('[module]/[entity]_category');
}
return $this->_categoryInstance;
}
public function getSelectedCategories(){
if (!$this->hasSelectedCategories()) {
$categories = array();
foreach ($this->getSelectedCategoriesCollection() as $category) {
$categories[] = $category;
}
$this->setSelectedCategories($categories);
}
return $this->getData('selected_categories');
}
public function getSelectedCategoriesCollection(){
$collection = $this->getCategoryInstance()->getCategoryCollection($this);
return $collection;
}
Itu saja. Saya harap saya tidak melewatkan apa pun. Kode mungkin memerlukan beberapa perubahan karena saya tidak tahu bagaimana tepatnya modul Anda dibangun, tetapi ide-ide utama ada di sana. Dengan beberapa debug, Anda harus membuatnya berfungsi.
Catatan: Kode di atas dibuat menggunakan Ultimate Module Creator v1.9 .
Setidaknya untuk Magento 1.9 Anda harus yakin bahwa extJs dimuat.
Gunakan salah satu metode berikut untuk mengaktifkan penggunaan extJS di backend:
Di controller Anda gunakan ini:
$this->getLayout()->getBlock('head')->setCanLoadExtJs(true);
Di layout Anda xml gunakan ini:
<reference name="head">
<action method="setCanLoadExtJs">
<value>1</value>
</action>
</reference>