可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In Magento you can override a block (or helper, or model, etc.) from one module in another one (most common from Magento Adminhtml module). Now I have the problem that I want to override a block that was already overriden by some other extension. Is there any way to tell magento to ignore the <rewrite>
tag in some other module configuration similary to the <remove>
tag in layout updates?
Here is the configuration of the other extension:
<blocks>
<adminhtml>
<rewrite>
<catalog_product_grid>Symmetrics_DeliveryTime_Block_Adminhtml_Catalog_Product_Grid</catalog_product_grid>
</rewrite>
</adminhtml>
</blocks>
Here the configuration of my extension:
<blocks>
<adminhtml>
<rewrite>
<catalog_product_grid>Namespace_MyModule_Block_Adminhtml_Catalog_Product_Grid</catalog_product_grid>
</rewrite>
</adminhtml>
</blocks>
I integrated the functionality of the block from Symmetrics_DeliveryTime
into my own block and now I want magento to ignore the block overriding from that module.
Is there any magento way to do that or is the only way to comment out the configuration (which is what I have done for now) including all the hassle while updating that module later?
回答1:
If you set your module to 'depend' on the one that's also doing a rewrite, your config will be read last and the rewrite should stick, in the appropriate file within app/etc/modules you should have:
<config>
<modules>
<Your_Module>
<active>true</active>
<codePool>local</codePool>
<depends>
<Other_Module/>
</depends>
</Your_Module>
<modules>
<config>
回答2:
I took a look in the class loading, and it doesn't look like there is a clean solution. The relevant classname loading code is this:
if (isset($this->_classNameCache[$groupRootNode][$group][$class])) {
return $this->_classNameCache[$groupRootNode][$group][$class];
}
...
if (isset($config->rewrite->$class)) {
$className = (string)$config->rewrite->$class;
So it looks like there is no such thing as a rewritten-rewrite. The one that gets put into the configuration array is the one that gets loaded, and once cached it simply gets returned as requested. I don't see an easy way to hack the cache, either. You could try to get precedence for your module (by renaming it alphabetically, I assume), but that's a total hack and likely to fail mysteriously later on. That kills the config possibilities.
Also obnoxious: it looks like Magento only requests that grid in two places, within Mage_Adminhtml_Block_Catalog_Product
(which you can easily override), but also in Mage_Adminhtml_Catalog_ProductController
(d'oh!). Depending on your use case, consider overriding the catalog product block and replacing the _prepareLayout()
function with your own. If you want to override the controller as well, you'll want to create your own controller (which descends from Mage_Adminhtml_Catalog_ProductController
) and define a rewrite within your configuration to direct admin/catalog/product/grid
to your action. A pain, but at least accomplishes your goal.
Hope that helps,
Joe
回答3:
Instead of rewriting catalog_product_grid, why not extend on Symmetrics_DeliveryTime_Block_Adminhtml_Catalog_Product_Grid? That way the Symmetrics module will keep all it's functionalities and you can add yours.
So instead of:
<blocks>
<adminhtml>
<rewrite>
<catalog_product_grid>Symmetrics_DeliveryTime_Block_Adminhtml_Catalog_Product_Grid</catalog_product_grid>
</rewrite>
</adminhtml>
</blocks>
do this:
<blocks>
<adminhtml>
<rewrite>
<deliverytime_catalog_product_grid>Namespace_MyModule_Block_Adminhtml_Catalog_Product_Grid</deliverytime_catalog_product_grid>
</rewrite>
</adminhtml>
</blocks>
Of course than a depend in your app/etc/modules file would be fitting.
回答4:
The best way to overcome this problem using, layout after or before observer.
app/code/local/My/Module/etc/config.xml
<config>
<adminhtml>
<events>
<core_block_abstract_prepare_layout_before>
<observers>
<mymodule>
<!-- Add column to catalog product grid -->
<class>mymodule/adminhtml_observer</class>
<method>onBlockHtmlBefore</method>
</mymodule>
</observers>
</core_block_abstract_prepare_layout_before>
</events>
</adminhtml>
or can use event: core_block_abstract_prepare_layout_after.
And in Observer:
class My_Module_Model_Adminhtml_Observer
{
public function onBlockHtmlBefore(Varien_Event_Observer $observer) {
$block = $observer->getBlock();
if (!isset($block)) return;
switch ($block->getType()) {
case 'adminhtml/catalog_product_grid': //or here you can put any other block
/*For example i am using Mage_Adminhtml_Block_Catalog_Product_Grid, and want to add a column*/
$block->addColumn('COLUMN_ID', array(
'header' => Mage::helper('mymodule')->__('COLUMN HEADER'),
'index' => 'COLUMN_ID',
));
break;
case 'adminhtml/catalog_product_edit_tabs':
/*Or i want to add new tab to admin product edit*/
/* @var $block Mage_Adminhtml_Block_Catalog_Product_Edit_Tabs */
$block->addTab('tab_name', array(
'label' => Mage::helper('catalog')->__('Tab Tilte'),
'content' => $block->getLayout()->createBlock('modulename/adminhtml_product_edit_tabname')->toHtml(),
'after' => 'inventory',
));
break;
}
}
}
While adding tab then you can take reference of product edit tabs to add your form fields into that using you module.
Hope this will be helpful to some one :)