拡張機能がクラスをグローバルに上書きし、元のクラスを使用したい場合はどうすればよいですか?


42

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>

拡張機能は階層化されたナビゲーションカテゴリのコンテキストで機能しますが、独自の社内モジュールの別の(カスタム)ビューに任意の製品リストを挿入すると、書き換えられたクラスは適切に機能しません。テストのためだけに拡張機能を上書きする場合は、すべて正常に動作します。

拡張機能の開発者のコ​​ミュニティコードを編集せずに、独自のコントローラーだけで拡張機能の書き換えを元に戻すにはどうすればよいですか?


2
あなたは、クラスを変更する場合は、おそらくShopby拡張子を破るだろうけど...決してしかしあなたは自分自身の拡張でその拡張クラスYour_Extension_Block_Catalog_Product_List_ToolbarがAmasty_Shopby_Block_Catalog_Product_List_Toolbarを拡張して書き換えることもできます、これを試してみました
サンダーMangel

私が知る限り、Magentoでは<rewrite>クラスごとに1 つしか許可されていないため、コアクラスを拡張する独自のクラスを作成できますが、getBlock('catalog/product_list_toolbar')ファクトリメソッドを介してどのように動作するのかわかりません。
アーロンポロック

有料の拡張機能である場合は、Amastyサポートに連絡する必要があります。これはバグとして表示されます
Fra

問題を特定できましたか?あなたが直面している問題の原因は何ですか(拡張クラスで機能します)?
FlorinelChis

1
@AaronPollockかもしれませんが、この問題は、必要なだけ正確に内容を上書きする拡張機能から発生する可能性があります。おそらく、継承モデル自体を再検討する方が良いでしょう。たぶん、ミックスインや特性が役立つでしょう。
小次郎

回答:


25

警告:システムで要求していることを実行するように設計された方法はありません。以下は動作するはずですが、実稼働システムで広範囲に試したことは一度もないので、それだけの価値のあるトラブルを引き起こす場合があります。作業中のシステムの書き換えの変更に関連する問題をデバッグするのが快適な場合にのみ続行してください。

ステップ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_predispatchcontroller_action_predispatch_front_controller_actionイベントや条件付きで適用できます。

このメソッドが呼び出されるまで、書き換えは元に戻されないことを覚えておいてください。つまり、を呼び出す前にブロックをインスタンス化しようとすると_undoRewrites、書き換えられたクラスがオブジェクトのインスタンス化に使用されます。


19

解決策1:
コントローラーでクラスを直接(PHPの方法で)インスタンス化することができます。

の代わりに

$this->getLayout()->createBlock('catalog/product_list_toolbar');

何かのようなもの:

$block = New Magento_Catalog_Product_List_Toolbar;
$this->getLayout()->addBlock(....);

解決策2:
別のアプローチは、元のクラスを拡張し、そのクラスを使用する新しいクラスをモジュールに作成することです。

解決策3:
そうでなければ、拡張機能が暗号化されていない場合(私たちは皆オープンソースが大好きです:)あなたはそれがあなたのものを壊す理由を見つけることを試みることができます


解決策2は機能します(実用的な解決策)がrewrite、同じ基本クラスで2番目の操作を行うことができないという点で素晴らしいとは言えません。したがって、ファクトリメソッドは機能しません(これは既に理解していると思います)。たぶんこれを行うMagentoの方法はありませんが、少し良い方法があるかどうかを確認しましょう。
アーロンポロック

ソリューション2は私が行くことです...フランチェスコの答えを見るまで、私はそれを提案する準備ができていました。;)
デビダルガー

1
ソリューション2が一番好きですが、ソリューション1の注:createBlockに完全なクラス名を指定することもできます($this->getLayout()->createBlock("Mage_Catalog_Block_Product_List_Toolbar")ブロッククラスコンテキストにいるときのように)。/パラメータにない場合、Magentoはクラスを検索するために文字列をそのまま使用します。
マティアスツァイス

1
@Aaron Pollock、同じ基本クラスで2回目の書き換えを行うことができます。モジュールの名前空間にZ(Aの後の任意の文字)という名前を付けると、magentoはAmastyの代わりにそれを使用します。
アマスティ14

5

同じクラスエイリアスに対して複数の書き換えが存在する場合、Magento configローダーがconfig.xmlから最後に解析したものが「勝ちます」。私はこの問題を次のように攻撃します。

  1. 独自の新しい拡張機能を作成します。
  2. リライトcatalog/product_list_toolbarあなたの拡張機能で
  3. Mage_Catalog_Block_Product_List_ToolbarAmastyクラスの代わりにブロックを拡張します。
  4. この書き換えの競合は意図的なものであることを説明するクラスを自由にコメントしてください。MageRunを実行する別の開発者が、作成したばかりの書き換え競合を「修正」しようとするのは望ましくありません。
  5. 拡張機能のapp / etc / modules / blah.xmlファイルに依存関係を追加して、拡張機能がAmasty拡張機能の後にロードされるようにします。

1

Francescoが上記で提案したものと似ていますが、実際には完全なクラス名をgetModelに渡すことができると思います。このように、あなたはまだ同じことをいくらかやっていますが、それを行うためにコアメソッドを使用しています。私はこの方法の長所/短所を完全に確信しているわけではありませんが、これをアイデアとしてそこに放り出すと思っていました。

Mage::getModel('Mage_Catalog_Block_Product_List_Toolbar');

余談ですが、これがMagento2でクラスをロードする標準的な方法になると思います。


1

私が恐れている拡張コードを少し変更する必要があります。クラスを自分で書き換えるのではなく、クラスを拡張するようにconfig.xml変更Amasty_Shopby_Block_Catalog_Product_List_ToolbarしてくださいMage_Catalog_Block_Product_List_Toolbar


拡張コードはコアコードのように見えます-他の誰かのビジネス(きれいにアップグレードする能力を維持するため)。触れないようにする方法が必要です。また、問題は、Amastyクラスが任意の製品リストのコンテキストでコア機能を破壊することです。私は自分の機能を注入しません。コア機能を復活させる必要があります。私のクラスは、私があなたの解決策に従った場合、空になり、そこで試みた修正は上位のAmastyクラスによって上書きされます。
アーロンポロック

これは悪い習慣です。外部モジュールには常に手を触れないでください。モジュールを更新する必要がある場合は、新しいバージョン内ですべての変更をやり直す必要があります。これは保守性の面で悪夢になる可能性があります。
マイケルTürk13年

新しいブロックを作成し、Amastyツールバーから拡張する方がよいでしょう。逆の場合も同様です。
アマスティ14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.