拡張機能がクラスをグローバルに上書きし、元のクラスを使用したい場合はどうすればよいですか?
-
16-10-2019 - |
質問
Mage_Catalog_Block_Product_List_Toolbar ブロックをグローバルに上書きする拡張機能を使用しています。
<global>
<blocks>
<catalog>
<rewrite>
<product_list_toolbar>Amasty_Shopby_Block_Catalog_Product_List_Toolbar</product_list_toolbar>
</rewrite>
</catalog>
</blocks>
</global>
この拡張機能は階層化されたナビゲーション カテゴリのコンテキストで動作しますが、独自の社内モジュールの別の (カスタム) ビューに任意の製品リストを挿入すると、書き換えられたクラスが正しく動作しません。テスト目的のみで拡張子の上書きを削除すると、すべてが正常に動作します。
拡張機能開発者のコミュニティ コードを編集せずに、独自のコントローラのみの拡張機能の書き換えを元に戻すにはどうすればよいでしょうか?
解決
注意事項:システムには、要求されたことを実行するための設計された方法はありません。以下は機能するはずですが、実稼働システムで広範囲に試したことはありません。また、実行する価値があるほど多くの問題が発生する状況もあるかもしれません。動作中のシステムの書き換えの変更に関連する問題のデバッグに慣れている場合にのみ続行してください。
ステップ 1 では、書き換えを元に戻します。Magento 構成ツリーは実行時に変更できます。したがって、次のコードを実行すると、
$config = Mage::getConfig();
$config->setNode(
'global/blocks/catalog/rewrite/product_list_toolbar',
'Mage_Catalog_Block_Product_List_Toolbar'
);
その後、Magento はオリジナルをインスタンス化します。 Mage_Catalog_Block_Product_List_Toolbar
リクエストの残りの部分をブロックします。
ステップ 2 では、これをモジュール内のどこで呼び出すかを決定します。これはコントローラー専用であり、コントローラーの最後までインスタンス化されないブロックを書き換えているため、コントローラー クラスに次のようなメソッドを追加します。
protected function _undoRewrites()
{
$config = Mage::getConfig();
$config->setNode(
'global/blocks/catalog/rewrite/product_list_toolbar',
'Mage_Catalog_Block_Product_List_Toolbar'
);
}
そして、各アクションの開始時にこのメソッドを呼び出すだけです
public function indexAction()
{
$this->_undoRewrites();
$test = Mage::getSingleton('core/layout')->createBlock('catalog/product_list_toolbar');
var_dump($test);
}
これは少し不格好に思えるかもしれませんが、不格好であることは良い考えだと思います(つまり、当然のことですが、Magento のシステム オブジェクトを賢く使っている場合です。このための別の場所としては、 controller_action_predispatch
または controller_action_predispatch_front_controller_action
イベントや条件付きで適用されます。
このメソッドが呼び出されるまで、書き換えは元に戻されないことに注意してください。つまり、呼び出す前にブロックをインスタンス化しようとすると、 _undoRewrites
, 、書き換えられたクラスはオブジェクトのインスタンス化に使用されます。
他のヒント
解決策 1:
コントローラーでクラスを直接(PHPの方法で)インスタンス化してみることができます
の代わりに
$this->getLayout()->createBlock('catalog/product_list_toolbar');
何かのようなもの:
$block = New Magento_Catalog_Product_List_Toolbar;
$this->getLayout()->addBlock(....);
解決策 2:
別のアプローチは、モジュール内に元のクラスを拡張する新しいクラスを作成し、そのクラスを使用することです。
解決策 3:
それ以外の場合、拡張機能が暗号化されていない場合 (私たちは皆、オープンソースが大好きです:) 拡張機能があなたのものを壊す理由を調べてみることができます
同じクラスエイリアスに複数の書き換えが存在する場合、Magento 設定ローダーが config.xml から解析した最後のものが「優先」されます。私なら次のようにしてこの問題に取り組みます。
- 独自の新しい拡張機能を作成します。
- を書き換えます
catalog/product_list_toolbar
あなたの内線番号で - ブロックを拡張してもらいます
Mage_Catalog_Block_Product_List_Toolbar
アマスティクラスの代わりに。 - この書き換えの競合が意図的なものであることを説明するために、クラスに積極的にコメントしてください。MageRun を実行する別の開発者が、作成したばかりの書き換え競合を「修正」しようとすることを望まないでしょう。
- 拡張機能の app/etc/modules/blah.xml ファイルに依存関係を追加して、拡張機能が Amaty 拡張機能の後にロードされるようにします。
上記で Francesco が提案したものと似ていますが、実際には完全なクラス名を getModel に渡すことができると思います。この方法では、同じことを行っていることになりますが、コアメソッドを使用してそれを実行します。この方法の長所/短所はよくわかりませんが、アイデアとしてこれを投げてみようと思いました。
Mage::getModel('Mage_Catalog_Block_Product_List_Toolbar');
余談ですが、これが Magento2 でクラスをロードする標準的な方法になると思います。
残念ですが、拡張コードを少し変更する必要があります。クラスを自分で書き直さないでください config.xml
もう、変えるだけ Amasty_Shopby_Block_Catalog_Product_List_Toolbar
クラスを拡張すると、クラスも拡張されます Mage_Catalog_Block_Product_List_Toolbar
.