3

Magento ストアのカスタム モジュールの作成に問題があります。

ルート (/landing) を正常に追加し、ベース レイアウト内にテンプレート コンテンツを表示するレイアウト ファイルを作成しました。私は今、それを少し超える必要があります。

URL からパラメーターを読み込み、そのパラメーターに基づいてオブジェクトを取得し、オブジェクトのコンテンツに基づいて表示できるようにしたいと考えています。

例: domain.com/landing/cool/ へのユーザー ブラウザー。これは (うまくいけば) 着陸コントローラーを呼び出します。コントローラーは何らかの方法で「cool」パラメーターを取得し、cool に関連付けられた着陸オブジェクトを取得できます。次に、テンプレートでそのオブジェクトを取得して、その要素を表示できます。

そこにはたくさんのビットがあることは知っていますが、しばらくの間、これについて頭を悩ませていましたが、どこにも行き着きませんでした。Magentoは、そのすべてのカテゴリ、アイテムなどに対してこれを行う必要があります.誰かが私がそれを行う方法を知っていますか?

4

4 に答える 4

2

以下の説明は、通常の方法でフロントネームを定義したことを前提としています:

<config>
    <modules>
        <Mycompany_Landing>
            <version>0.1.0</version>
        </Mycompany_Landing>
    </modules>
    <frontend>
        <routers>
            <landing>
                <use>standard</use>
                <args>
                    <module>Mycompany_Landing</module>
                    <frontName>landing</frontName>
                </args>
            </landing>
        </routers>
    </frontend>
</config>

このシナリオでは、Magento 標準ルーターは URLlanding/cool

Mycompany_Landing_CoolController::indexAction()

これは、Magento 標準ルーターがfrontname/controller/actionパターンを使用して URL を処理し、あなたの場合はそれを認識しているためです。

  • フロントネームはで、モジュールlandingにマッピングされていますMycompany_Landing
  • コントローラ名はcoolで、これは次のように変換されますCoolController
  • アクション名が欠落しているため、indexActionデフォルトで使用されます

ただし、コントローラーではなく、パラメーターになりたいcoolと考えています。

この背後にある理由は、 、landing/coolなどの他に複数のランディング ゾーンが必要だということだと思います。これは、異なるランディング ゾーンごとに 1 つずつ、複数のコントローラーをセットアップする必要があることを意味します。landing/awesomelanding/insane

この場合、複数のコントローラーを回避するための可能な解決策は、独自のルーターを実装することです。

独自のルーターの実装

独自のルーターを実装するには、次のようcontroller_front_init_routersに拡張して、イベントにフックする必要があります。app/code/local/Mycompany/Landing/etc/config.xml

<config>
    <global>
        <events>
            <controller_front_init_routers>
                <observers>
                    <landing>
                        <class>Mycompany_Landing_Controller_Router</class>
                        <method>controllerFrontInitRouters</method>
                    </landing>
                </observers>
            </controller_front_init_routers>
        </events>
    </global>
</config>

次に、適切なapp/code/local/Mycompany/Landing/Controller/Router.phpファイルを作成します。

class Mycompany_Landing_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract
{

    /**
     * Add own router to Magento router chain
     *
     * @param Varien_Event_Observer $oObserver
     */

    public function controllerFrontInitRouters($oObserver)
    {
        // Add this router to the current router chain
        $oObserver
            ->getEvent()
            ->getFront()
            ->addRouter('landing', $this);
    }

    /**
     * Match routes for the landing module
     *
     * @param Zend_Controller_Request_Http $oRequest
     * @return bool
     */

    public function match(Zend_Controller_Request_Http $oRequest)
    {

        $sPathInfo = trim($oRequest->getPathInfo(), '/');
        $aPathInfo = explode('/', $sPathInfo);

        // Cancel if the route request is for some other module
        if ($aPathInfo[0] != 'landing') {
            return false;
        }

        // Cancel if it's not a valid landing zone
        if (!in_array($aPathInfo[1], array('cool'))) {
            return false;
        }

        // Rewrite the request object
        $oRequest
            ->setModuleName('landing')
            ->setControllerName('index')
            ->setActionName('index')
            ->setParam('zone', $aPathInfo[1])
            ->setAlias(
                'landing_router_rewrite',
                true
            );

        // Tell Magento that this router can match the request
        return true;

    }

}

上記controllerFrontInitRouters()のファイルのメソッドでは、独自のルーターが Magento ルーター チェーンにマージされ、次のようになります。

Mage_Core_Controller_Varien_Router_Admin
Mage_Core_Controller_Varien_Router_Standard
Mage_Cms_Controller_Router
Mycompany_Landing_Controller_Router
Mage_Core_Controller_Varien_Router_Default

Magento は、ディスパッチ時に指定された順序でこのチェーンをループします。つまり、あなたのようなカスタム ルーターは、常に最初の 4 番目の位置で呼び出されます。ルーターは、前の 3 つのルーターのいずれもルート要求に一致しない場合にのみ呼び出されます。

match()ファイルのメソッドが呼び出され、有効なルート (現在landing/coolのみ) が検出されると、リクエスト オブジェクトが変更され、値Mycompany_Landing_IndexController::indexAction()を持つパラメータがディスパッチされます。zonecool

これmatch()は単純化しすぎていることに注意してください。消毒などは含まれていません。これを修正することを忘れないでください^^

最後にapp/code/local/Mycompany/Landing/controllers/IndexController.phpファイルを作成します。

class Mycompany_Landing_IndexController extends Mage_Core_Controller_Front_Action
{

    public function indexAction()
    {

        if (!$this->getRequest()->getAlias('landing_router_rewrite')) {
            $this->_forward('noRoute');
            return;
        }

        $sZone = $this->getRequest()->getParam('zone');

        die(__METHOD__ . ' called with zone = ' . $sZone);

    }

}

リクエスト オブジェクトにエイリアスが設定されていない場合、最初のifブロックはアクションをキャンセルします (ルーターのメソッドを参照してください)。indexActionlanding_route_rewritesetAlias()match()

これは、ユーザーが、、、indexAction()などの他の URL を使用してこれに到達する可能性があるためです。landinglanding/indexlandig/index/indexlanding/index/index/zone/cool

このような他の URL を SEO ランク付けしたり、検証とサニタイズを 2 回実装したりすることは望ましくないと思いますが、必要ない場合は、そのifブロックを削除してください。

これで、 を拡張しindexAction()て、ランディング ゾーンでやりたいことが何でもできるようになりました。

于 2012-08-12T15:19:36.737 に答える
2

domain.com/landing/[controller]/cool/[key]/[value] を実行すると、$this->getRequest()->getParam('[key]') を実行して [value] の値を取得できます。 ]。それに基づいてテンプレートを設定できますが、それは別の問題だと思います。まだ混乱している場合はお知らせください。

于 2012-08-01T19:53:32.450 に答える
1

ここでもう少し詳しく調べていますが、今頭に浮かんでいるのは、「/」で爆発してそれらをつかむことだけです。

于 2012-08-01T19:57:45.537 に答える
0

私のプロジェクトの1つでJavascriptを使用してそれを行った方法は次のとおりです。

function populateSelect(url, element, target) {
    var selectedValue = document.getElementById(element);
    var elementValue = selectedValue.options[selectedValue.selectedIndex].value;

    pathArray = url.split( '/' );
    pathArray.shift();
    pathArray.shift();
    pathArray.splice(5,0, element);
    pathArray.splice(6,0, elementValue);
    url = pathArray.join("/");
    url = 'http://' + url;

    new Ajax.Request(url, {
        method:    "POST",
        onSuccess:
            function(transport) {
                var json    = transport.responseText.evalJSON(true);
                var options = '';
                $(target).descendants().each(Element.remove);

                 for (var i = 0; i < json.length; i++) {
                    var opt = document.createElement('option');
                    opt.text = json[i].optionName;
                    opt.value = json[i].optionValue;
                    $(target).options.add(opt);
                }
            }
    });
}
于 2012-08-01T20:02:01.577 に答える